OpenTREP Logo  0.07.20
C++ Open Travel Request Parsing Library
Loading...
Searching...
No Matches
DBManager.cpp
Go to the documentation of this file.
1// //////////////////////////////////////////////////////////////////////
2// Import section
3// //////////////////////////////////////////////////////////////////////
4// STL
5#include <cassert>
6#include <sstream>
7// Boost
8#include <boost/lexical_cast.hpp>
9#include <boost/date_time/gregorian/gregorian.hpp>
10#include <boost/filesystem.hpp>
11#include <boost/algorithm/string.hpp>
12// SOCI
13#include <soci/soci.h>
14#include <soci/sqlite3/soci-sqlite3.h>
15#include <soci/mysql/soci-mysql.h>
16#include <soci/postgresql/soci-postgresql.h>
17// OpenTrep
18#include <opentrep/Location.hpp>
31
32namespace OPENTREP {
33
34 // //////////////////////////////////////////////////////////////////////
36 const DeploymentNumber_T& iDeploymentNumber) {
37 bool oCreationSuccessful = true;
38 try {
39
40 // Retrieve the full file-path of the SQLite3 directory
41 boost::filesystem::path lSQLiteDBFullPath (iSQLDBConnStr.begin(),
42 iSQLDBConnStr.end());
43 // Retrieve the directory hosting the SQLite3 database
44 boost::filesystem::path lSQLiteDBParentPath =
45 lSQLiteDBFullPath.parent_path();
46
47 // DEBUG
48 OPENTREP_LOG_DEBUG ("The SQLite database file ('" << lSQLiteDBFullPath
49 << "') will be cleared and re-created");
50
51 // Delete the SQL database/file and its directory
52 boost::filesystem::remove_all (lSQLiteDBFullPath);
53
54 // Re-create the SQLite3 directory
55 boost::filesystem::create_directories (lSQLiteDBParentPath);
56
57 // Check whether the just created directory exists and is a directory.
58 //boost::filesystem::path lSQLiteDBFilename=lSQLiteDBFullPath.filename();
59 if (!(boost::filesystem::exists (lSQLiteDBParentPath)
60 && boost::filesystem::is_directory (lSQLiteDBParentPath))) {
61 std::ostringstream oStr;
62 oStr << "Error. The path to the SQLite3 database directory ('"
63 << lSQLiteDBParentPath
64 << "') does not exist or is not a directory.";
65 OPENTREP_LOG_ERROR (oStr.str());
66 throw FileNotFoundException (oStr.str());
67 }
68
69 } catch (std::exception const& lException) {
70 std::ostringstream errorStr;
71 errorStr << "Error when trying to create " << iSQLDBConnStr
72 << " SQLite3 database file: " << lException.what();
73 errorStr << ". Check that the program has got write permission on the "
74 << "corresponding parent directories.";
75 OPENTREP_LOG_ERROR (errorStr.str());
76 throw SQLDatabaseFileCannotBeCreatedException (errorStr.str());
77 }
78
79 // DEBUG
80 OPENTREP_LOG_DEBUG ("The SQLite database ('" << iSQLDBConnStr
81 << "') has been cleared and re-created");
82
83 //
84 return oCreationSuccessful;
85 }
86
87 // //////////////////////////////////////////////////////////////////////
89 const DeploymentNumber_T& iDeploymentNumber) {
90 bool oCreationSuccessful = true;
91
92 // DEBUG
93 OPENTREP_LOG_DEBUG ("Create the '"
95 << "' user and '" << DEFAULT_OPENTREP_MYSQL_DB_DBNAME
96 << iDeploymentNumber
97 << "' database in MySQL/MariaDB ('" << iSQLDBConnStr
98 << "')");
99
100 // Connection to the MySQL/MariaDB database
101 soci::session* lSociSession_ptr = NULL;
102 try {
103
104 // Connect to the SQL database/file
105 lSociSession_ptr = DBManager::initSQLDBSession (DBType::MYSQL,
106 iSQLDBConnStr);
107 if (lSociSession_ptr == NULL) {
108 oCreationSuccessful = false;
109 return oCreationSuccessful;
110 }
111
112 } catch (soci::mysql_soci_error const& lSociException) {
113 std::ostringstream errorStr;
114 errorStr << "SOCI-related error when trying to connect to the "
115 << "MySQL/MariaDB database ('" << iSQLDBConnStr
116 << "'). SOCI error message: " << lSociException.what();
117 OPENTREP_LOG_ERROR (errorStr.str());
118 std::cerr << errorStr.str() << std::endl;
119 oCreationSuccessful = false;
120 return oCreationSuccessful;
121 }
122 assert (lSociSession_ptr != NULL);
123 soci::session& lSociSession = *lSociSession_ptr;
124
152
153 try {
154 // Drop user 'trep'@'localhost'
155 std::ostringstream lSQLDropTrepLocalStr;
156 lSQLDropTrepLocalStr << "drop user '"
159 lSociSession << lSQLDropTrepLocalStr.str();
160
161 // Drop user 'trep'@'%'
162 std::ostringstream lSQLDropTrepAllStr;
163 lSQLDropTrepAllStr << "drop user '"
164 << DEFAULT_OPENTREP_MYSQL_DB_USER << "'@'%';";
165 lSociSession << lSQLDropTrepAllStr.str();
166
167 } catch (soci::mysql_soci_error const& lSociException) {
168 std::ostringstream issueStr;
169 issueStr << "Issue when trying to drop MySQL/MariaDB '"
170 << DEFAULT_OPENTREP_MYSQL_DB_USER << "' user. "
171 << "Most probably the user did not exist before. " << std::endl
172 << "SOCI error message: " << lSociException.what() << std::endl
173 << "The database users should however be created without "
174 << "any issue ";
175 OPENTREP_LOG_DEBUG (issueStr.str());
176 std::cout << issueStr.str() << std::endl;
177 }
178
179 try {
180 // Create user 'trep'@'localhost'
181 std::ostringstream lSQLCreateTrepLocalStr;
182 lSQLCreateTrepLocalStr << "create user '"
185 lSQLCreateTrepLocalStr << "identified by '"
187 lSociSession << lSQLCreateTrepLocalStr.str();
188
189 // Grant privileges to 'trep'@'localhost'
190 std::ostringstream lSQLGrantTrepLocalStr;
191 lSQLGrantTrepLocalStr << "grant SELECT, INSERT, UPDATE, DELETE, ";
192 lSQLGrantTrepLocalStr << "CREATE, DROP, FILE, INDEX, ALTER, ";
193 lSQLGrantTrepLocalStr << "CREATE TEMPORARY TABLES, CREATE VIEW, EVENT, ";
194 lSQLGrantTrepLocalStr << "TRIGGER, SHOW VIEW, CREATE ROUTINE, ";
195 lSQLGrantTrepLocalStr << "ALTER ROUTINE, EXECUTE ON *.*";
196 lSQLGrantTrepLocalStr << " to '" << DEFAULT_OPENTREP_MYSQL_DB_USER
197 << "'@'" << DEFAULT_OPENTREP_MYSQL_DB_HOST << "';";
198 lSociSession << lSQLGrantTrepLocalStr.str();
199
200 // Create user 'trep'@'%'
201 std::ostringstream lSQLCreateTrepAllStr;
202 lSQLCreateTrepAllStr << "create user '"
204 << "'@'%' identified by '"
206 lSociSession << lSQLCreateTrepAllStr.str();
207
208 // Grant privileges to 'trep'@'%'
209 std::ostringstream lSQLGrantTrepAllStr;
210 lSQLGrantTrepAllStr << "grant SELECT, INSERT, UPDATE, DELETE, ";
211 lSQLGrantTrepAllStr << "CREATE, DROP, FILE, INDEX, ALTER, ";
212 lSQLGrantTrepAllStr << "CREATE TEMPORARY TABLES, CREATE VIEW, EVENT, ";
213 lSQLGrantTrepAllStr << "TRIGGER, SHOW VIEW, CREATE ROUTINE, ";
214 lSQLGrantTrepAllStr << "ALTER ROUTINE, EXECUTE ON *.*";
215 lSQLGrantTrepAllStr << " to '" << DEFAULT_OPENTREP_MYSQL_DB_USER
216 << "'@'%';";
217 lSociSession << lSQLGrantTrepAllStr.str();
218
219 // Flush privileges
220 std::ostringstream lSQLFlushPrivilegesStr;
221 lSQLFlushPrivilegesStr << "flush privileges;";
222 lSociSession << lSQLFlushPrivilegesStr.str();
223
224 } catch (soci::mysql_soci_error const& lSociException) {
225 oCreationSuccessful = false;
226 std::ostringstream errorStr;
227 errorStr << "SOCI-related error when trying to create MySQL/MariaDB "
229 << "' user. Error message: " << lSociException.what();
230 OPENTREP_LOG_ERROR (errorStr.str());
231 std::cerr << errorStr.str() << std::endl;
232 oCreationSuccessful = false;
233 return oCreationSuccessful;
234 }
235
244 try {
245 // Drop the 'trep_trep' database, if existing
246 std::ostringstream lSQLDropDBStr;
247 lSQLDropDBStr << "drop database if exists "
248 << DEFAULT_OPENTREP_MYSQL_DB_DBNAME << iDeploymentNumber
249 << ";";
250 lSociSession << lSQLDropDBStr.str();
251
252 // Create the 'trep_trep' database
253 std::ostringstream lSQLCreateDBStr;
254 lSQLCreateDBStr << "create database if not exists "
255 << DEFAULT_OPENTREP_MYSQL_DB_DBNAME << iDeploymentNumber;
256 lSQLCreateDBStr << " default character set utf8mb4";
257 lSQLCreateDBStr << " collate utf8mb4_unicode_ci;";
258 lSociSession << lSQLCreateDBStr.str();
259
260 } catch (soci::mysql_soci_error const& lSociException) {
261 oCreationSuccessful = false;
262 std::ostringstream errorStr;
263 errorStr << "SOCI-related error when trying to create MySQL/MariaDB "
264 << "'" << DEFAULT_OPENTREP_MYSQL_DB_DBNAME << iDeploymentNumber
265 << "' database with 'utf8mb4' as character set. "
266 << "Error message: " << lSociException.what();
267 OPENTREP_LOG_ERROR (errorStr.str());
268 std::cerr << errorStr.str() << std::endl;
269 }
270 if (oCreationSuccessful == false) {
271 try {
272 // Drop the 'trep_trep' database, if existing
273 std::ostringstream lSQLDropDBStr;
274 lSQLDropDBStr << "drop database if exists "
275 << DEFAULT_OPENTREP_MYSQL_DB_DBNAME << iDeploymentNumber
276 << ";";
277 lSociSession << lSQLDropDBStr.str();
278
279 // Create the 'trep_trep' database
280 std::ostringstream lSQLCreateDBStr;
281 lSQLCreateDBStr << "create database if not exists "
283 << iDeploymentNumber;
284 lSQLCreateDBStr << " default character set utf8";
285 lSQLCreateDBStr << " collate utf8_unicode_ci;";
286 lSociSession << lSQLCreateDBStr.str();
287
288 } catch (soci::mysql_soci_error const& lSociException) {
289 oCreationSuccessful = false;
290 std::ostringstream errorStr;
291 errorStr << "SOCI-related error when trying to create MySQL/MariaDB "
293 << iDeploymentNumber
294 << "' database. Error message: " << lSociException.what();
295 OPENTREP_LOG_ERROR (errorStr.str());
296 std::cerr << errorStr.str() << std::endl;
297 oCreationSuccessful = false;
298 return oCreationSuccessful;
299 }
300 }
301
302 // DEBUG
304 << "' user and '" << DEFAULT_OPENTREP_MYSQL_DB_DBNAME
305 << iDeploymentNumber
306 << "' database have been created in MySQL/MariaDB ('"
307 << iSQLDBConnStr << "')");
308 //
309 return oCreationSuccessful;
310 }
311
312 // //////////////////////////////////////////////////////////////////////
314 const DeploymentNumber_T& iDeploymentNumber) {
315 bool oCreationSuccessful = true;
316
317
318 // DEBUG
319 OPENTREP_LOG_DEBUG ("Create the '"
321 << "' user and '" << DEFAULT_OPENTREP_PG_DB_DBNAME
322 << iDeploymentNumber
323 << "' database in PostgreSQL ('" << iSQLDBConnStr
324 << "')");
325
326 // Connection to the PostgreSQL database
327 soci::session* lSociSession_ptr = NULL;
328 try {
329
330 // Connect to the SQL database/file
331 lSociSession_ptr = DBManager::initSQLDBSession (DBType::PG,
332 iSQLDBConnStr);
333 if (lSociSession_ptr == NULL) {
334 oCreationSuccessful = false;
335 return oCreationSuccessful;
336 }
337
338 } catch (soci::mysql_soci_error const& lSociException) {
339 std::ostringstream errorStr;
340 errorStr << "SOCI-related error when trying to connect to the "
341 << "PostgreSQL database ('" << iSQLDBConnStr
342 << "'). SOCI error message: " << lSociException.what();
343 OPENTREP_LOG_ERROR (errorStr.str());
344 std::cerr << errorStr.str() << std::endl;
345 oCreationSuccessful = false;
346 return oCreationSuccessful;
347 }
348 assert (lSociSession_ptr != NULL);
349 // soci::session& lSociSession = *lSociSession_ptr;
350
351 //
352 // TODO - Adapt the remaining of the MySQL function
353 //
354
355 //
356 return oCreationSuccessful;
357 }
358
359 // //////////////////////////////////////////////////////////////////////
361 createSQLDBUser (const DBType& iDBType,
362 const SQLDBConnectionString_T& iSQLDBConnStr,
363 const DeploymentNumber_T& iDeploymentNumber) {
364 bool oCreationSuccessful = true;
365
366 // Retrieve the enum, so that the switch-case statement works
367 const DBType::EN_DBType& dbType = iDBType.getType();
368
369 switch (dbType) {
370 case DBType::SQLITE3: {
371 oCreationSuccessful = createSQLDBUserOnSQLite(iSQLDBConnStr,
372 iDeploymentNumber);
373 break;
374 }
375
376 case DBType::MYSQL: {
377 oCreationSuccessful = createSQLDBUserOnMySQL(iSQLDBConnStr,
378 iDeploymentNumber);
379
380 break;
381 }
382
383 case DBType::PG: {
384 oCreationSuccessful = createSQLDBUserOnPG(iSQLDBConnStr,
385 iDeploymentNumber);
386
387 break;
388 }
389
390 default: {
391 break;
392 }
393 }
394
395 return oCreationSuccessful;
396 }
397
398 // //////////////////////////////////////////////////////////////////////
399 soci::session* DBManager::
400 initSQLDBSession (const DBType& iDBType,
401 const SQLDBConnectionString_T& iSQLDBConnStr) {
402 soci::session* oSociSession_ptr = NULL;
403
404 // Retrieve the enum, so that the switch-case statement works
405 const DBType::EN_DBType& dbType = iDBType.getType();
406
407 // DEBUG
408 if (dbType != DBType::NODB) {
409 OPENTREP_LOG_DEBUG ("Connecting to the " << iDBType.describe()
410 << " SQL database/file ('" << iSQLDBConnStr << "')");
411 }
412
413 switch (dbType) {
414 case DBType::SQLITE3: {
415 // Check that the directory hosting the SQLite database exists
416 const bool existSQLDBDir =
417 FileManager::checkSQLiteDirectory (iSQLDBConnStr);
418 if (existSQLDBDir == false) {
419 std::ostringstream errorStr;
420 errorStr << "Error when trying to connect to the '" << iSQLDBConnStr
421 << "' SQLite3 database; the directory hosting that "
422 << "database does not exist or is not readable";
423 OPENTREP_LOG_ERROR (errorStr.str());
424 throw SQLDatabaseImpossibleConnectionException (errorStr.str());
425 }
426
427 try {
428
429 // Connect to the SQL database.
430 oSociSession_ptr = new soci::session();
431 assert (oSociSession_ptr != NULL);
432 soci::session& lSociSession = *oSociSession_ptr;
433 lSociSession.open (soci::sqlite3, iSQLDBConnStr);
434
435 // DEBUG
436 OPENTREP_LOG_DEBUG ("The SQLite3 database/file ('" << iSQLDBConnStr
437 << "') has been checked and opened");
438
439 } catch (std::exception const& lException) {
440 std::ostringstream errorStr;
441 errorStr << "Error when trying to connect to the '" << iSQLDBConnStr
442 << "' SQLite3 database: " << lException.what();
443 OPENTREP_LOG_ERROR (errorStr.str());
444 throw SQLDatabaseImpossibleConnectionException (errorStr.str());
445 }
446
447 // The SQLite3 connection is assumed to have been successful
448 assert (oSociSession_ptr != NULL);
449
450 break;
451 }
452
453 case DBType::MYSQL: {
454 try {
455
456 // Connect to the SQL database.
457 oSociSession_ptr = new soci::session();
458 assert (oSociSession_ptr != NULL);
459 soci::session& lSociSession = *oSociSession_ptr;
460 lSociSession.open (soci::mysql, iSQLDBConnStr);
461
462 // DEBUG
463 OPENTREP_LOG_DEBUG ("The " << iDBType.describe() << " database ("
464 << iSQLDBConnStr << ") is accessible");
465
466 } catch (std::exception const& lException) {
467 std::ostringstream errorStr;
468 errorStr << "Error when trying to connect to the '" << iSQLDBConnStr
469 << "' MySQL/MariaDB database: " << lException.what();
470 OPENTREP_LOG_ERROR (errorStr.str());
471 throw SQLDatabaseImpossibleConnectionException (errorStr.str());
472 }
473
474 // The MySQL/MariaDB connection is assumed to have been successful
475 assert (oSociSession_ptr != NULL);
476
477 break;
478 }
479
480 case DBType::PG: {
481 try {
482
483 // Connect to the SQL database.
484 oSociSession_ptr = new soci::session();
485 assert (oSociSession_ptr != NULL);
486 soci::session& lSociSession = *oSociSession_ptr;
487 lSociSession.open (soci::postgresql, iSQLDBConnStr);
488
489 // DEBUG
490 OPENTREP_LOG_DEBUG ("The " << iDBType.describe() << " database ("
491 << iSQLDBConnStr << ") is accessible");
492
493 } catch (std::exception const& lException) {
494 std::ostringstream errorStr;
495 errorStr << "Error when trying to connect to the '" << iSQLDBConnStr
496 << "' PostgreSQL database: " << lException.what();
497 OPENTREP_LOG_ERROR (errorStr.str());
498 throw SQLDatabaseImpossibleConnectionException (errorStr.str());
499 }
500
501 // The PostgreSQL connection is assumed to have been successful
502 assert (oSociSession_ptr != NULL);
503
504 break;
505 }
506
507 case DBType::NODB: {
508 // Do nothing
509
510 break;
511 }
512
513 default: {
514 std::ostringstream errorStr;
515 errorStr << "Error: the '" << iDBType.describe()
516 << "' SQL database type is not supported";
517 OPENTREP_LOG_ERROR (errorStr.str());
518 throw SQLDatabaseTableCreationException (errorStr.str());
519 break;
520 }
521 }
522
523 return oSociSession_ptr;
524 }
525
526 // //////////////////////////////////////////////////////////////////////
528 terminateSQLDBSession (const DBType& iDBType,
529 const SQLDBConnectionString_T& iSQLDBConnStr,
530 soci::session& ioSociSession) {
531 // Retrieve the enum, so that the switch-case statement works
532 const DBType::EN_DBType& dbType = iDBType.getType();
533
534 // DEBUG
535 if (dbType != DBType::NODB) {
536 OPENTREP_LOG_DEBUG ("Connecting to the " << iDBType.describe()
537 << " SQL database/file ('" << iSQLDBConnStr << "')");
538 }
539
540 switch (dbType) {
541 case DBType::SQLITE3: {
542 try {
543
544 // Release the SQL database connection
545 ioSociSession.close();
546
547 } catch (std::exception const& lException) {
548 std::ostringstream errorStr;
549 errorStr << "Error when trying to release the connection ('"
550 << iSQLDBConnStr
551 << "') to the SQLite3 database: " << lException.what();
552 OPENTREP_LOG_ERROR (errorStr.str());
553 throw SQLDatabaseConnectionReleaseException (errorStr.str());
554 }
555
556 break;
557 }
558
559 case DBType::PG: {
560 try {
561
562 // Release the SQL database connection
563 ioSociSession.close();
564
565 } catch (std::exception const& lException) {
566 std::ostringstream errorStr;
567 errorStr << "Error when trying to release the connection ('"
568 << iSQLDBConnStr
569 << "') to the PostgreSQL database: " << lException.what();
570 OPENTREP_LOG_ERROR (errorStr.str());
571 throw SQLDatabaseConnectionReleaseException (errorStr.str());
572 }
573
574 break;
575 }
576
577 case DBType::MYSQL: {
578 try {
579
580 // Release the SQL database connection
581 ioSociSession.close();
582
583 } catch (std::exception const& lException) {
584 std::ostringstream errorStr;
585 errorStr << "Error when trying to release the connection ('"
586 << iSQLDBConnStr
587 << "') to the MySQL/MariaDB database: " << lException.what();
588 OPENTREP_LOG_ERROR (errorStr.str());
589 throw SQLDatabaseConnectionReleaseException (errorStr.str());
590 }
591 break;
592 }
593
594 case DBType::NODB: {
595 // Do nothing
596
597 break;
598 }
599
600 default: {
601 std::ostringstream errorStr;
602 errorStr << "Error: the '" << iDBType.describe()
603 << "' SQL database type is not supported";
604 OPENTREP_LOG_ERROR (errorStr.str());
605 throw SQLDatabaseTableCreationException (errorStr.str());
606 }
607 }
608 }
609
610 // //////////////////////////////////////////////////////////////////////
611 void DBManager::createSQLDBTables (soci::session& ioSociSession) {
612 const std::string& lDBName = ioSociSession.get_backend_name();
613 const DBType lDBType (lDBName);
614
615 // Retrieve the enum, so that the switch-case statement works
616 const DBType::EN_DBType& dbType = lDBType.getType();
617
618 // DEBUG
619 if (dbType != DBType::NODB) {
620 OPENTREP_LOG_DEBUG ("The tables of the " << lDBType.describe()
621 << " SQL database/file will be created/reset");
622 }
623
624 switch (dbType) {
625 case DBType::SQLITE3: {
626 // DEBUG
627 OPENTREP_LOG_DEBUG ("Create the optd_por table in the SQLite3 database");
628
629 try {
630
650
651 ioSociSession << "drop table if exists optd_por;";
652 std::ostringstream lSQLTableCreationStr;
653 lSQLTableCreationStr << "create table optd_por (";
654 lSQLTableCreationStr << "pk varchar(20) NOT NULL, ";
655 lSQLTableCreationStr << "location_type varchar(4) default NULL, ";
656 lSQLTableCreationStr << "iata_code varchar(3) default NULL, ";
657 lSQLTableCreationStr << "icao_code varchar(4) default NULL, ";
658 lSQLTableCreationStr << "faa_code varchar(4) default NULL, ";
659 lSQLTableCreationStr << "unlocode_code varchar(5) default NULL, ";
660 lSQLTableCreationStr << "uic_code int(11) default NULL, ";
661 lSQLTableCreationStr << "is_geonames varchar(1) default NULL, ";
662 lSQLTableCreationStr << "geoname_id int(11) default NULL, ";
663 lSQLTableCreationStr << "envelope_id int(11) default NULL, ";
664 lSQLTableCreationStr << "date_from date default NULL, ";
665 lSQLTableCreationStr << "date_until date default NULL, ";
666 lSQLTableCreationStr << "serialised_place varchar(12000) default NULL);";
667 ioSociSession << lSQLTableCreationStr.str();
668
669 } catch (std::exception const& lException) {
670 std::ostringstream errorStr;
671 errorStr << "Error when trying to create SQLite3 tables: "
672 << lException.what();
673 OPENTREP_LOG_ERROR (errorStr.str());
674 throw SQLDatabaseTableCreationException (errorStr.str());
675 }
676
677 // DEBUG
678 OPENTREP_LOG_DEBUG ("The optd_por table has been created in the SQLite3 database");
679 break;
680 }
681
682 case DBType::PG: {
683 // TODO
684 break;
685 }
686
687 case DBType::MYSQL: {
688 // DEBUG
689 OPENTREP_LOG_DEBUG ("Create the optd_por table in the MySQL database");
690
691 try {
692
712
713 ioSociSession << "drop table if exists optd_por;";
714 std::ostringstream lSQLTableCreationStr;
715 lSQLTableCreationStr << "create table optd_por (";
716 lSQLTableCreationStr << "pk varchar(20) NOT NULL, ";
717 lSQLTableCreationStr << "location_type varchar(4) default NULL, ";
718 lSQLTableCreationStr << "iata_code varchar(3) default NULL, ";
719 lSQLTableCreationStr << "icao_code varchar(4) default NULL, ";
720 lSQLTableCreationStr << "faa_code varchar(4) default NULL, ";
721 lSQLTableCreationStr << "unlocode_code varchar(5) default NULL, ";
722 lSQLTableCreationStr << "uic_code int(11) default NULL, ";
723 lSQLTableCreationStr << "is_geonames varchar(1) default NULL, ";
724 lSQLTableCreationStr << "geoname_id int(11) default NULL, ";
725 lSQLTableCreationStr << "envelope_id int(11) default NULL, ";
726 lSQLTableCreationStr << "date_from date default NULL, ";
727 lSQLTableCreationStr << "date_until date default NULL, ";
728 lSQLTableCreationStr << "serialised_place varchar(12000) default NULL); ";
729 ioSociSession << lSQLTableCreationStr.str();
730
731 } catch (std::exception const& lException) {
732 std::ostringstream errorStr;
733 errorStr << "Error when trying to create MySQL/MariaDB tables: "
734 << lException.what();
735 OPENTREP_LOG_ERROR (errorStr.str());
736 throw SQLDatabaseTableCreationException (errorStr.str());
737 }
738
739 // DEBUG
740 OPENTREP_LOG_DEBUG ("The optd_por table has been created in the MySQL database");
741
742 break;
743 }
744
745 case DBType::NODB: {
746 // Do nothing
747
748 break;
749 }
750
751 default: {
752 std::ostringstream errorStr;
753 errorStr << "Error: the '" << lDBName
754 << "' SQL database type is not supported";
755 OPENTREP_LOG_ERROR (errorStr.str());
756 throw SQLDatabaseTableCreationException (errorStr.str());
757 break;
758 }
759 }
760 }
761
762 // //////////////////////////////////////////////////////////////////////
763 void DBManager::createSQLDBIndexes (soci::session& ioSociSession) {
764 const std::string& lDBName = ioSociSession.get_backend_name();
765 const DBType lDBType (lDBName);
766
767 // Retrieve the enum, so that the switch-case statement works
768 const DBType::EN_DBType& dbType = lDBType.getType();
769
770 // DEBUG
771 if (dbType != DBType::NODB) {
772 OPENTREP_LOG_DEBUG ("The indexes of the " << lDBType.describe()
773 << " SQL database/file will be created/reset");
774 }
775
776 switch (dbType) {
777 case DBType::SQLITE3: {
778 // DEBUG
779 OPENTREP_LOG_DEBUG ("Create the indices for the SQLite3 database");
780
781 try {
782
793
794 ioSociSession
795 << "create index optd_por_iata_code on optd_por (iata_code);";
796 ioSociSession
797 << "create index optd_por_iata_date on optd_por (iata_code, date_from, date_until);";
798 ioSociSession
799 << "create index optd_por_icao_code on optd_por (icao_code);";
800 ioSociSession
801 << "create index optd_por_geonameid on optd_por (geoname_id);";
802 ioSociSession
803 << "create index optd_por_unlocode_code on optd_por (unlocode_code);";
804 ioSociSession
805 << "create index optd_por_uic_code on optd_por (uic_code);";
806
807 } catch (std::exception const& lException) {
808 std::ostringstream errorStr;
809 errorStr << "Error when trying to create SQLite3 indexes: "
810 << lException.what();
811 OPENTREP_LOG_ERROR (errorStr.str());
812 throw SQLDatabaseIndexCreationException (errorStr.str());
813 }
814
815 // DEBUG
816 OPENTREP_LOG_DEBUG ("The indices have been created "
817 "for the SQLite3 database");
818 break;
819 }
820
821 case DBType::PG: {
822 // TODO
823
824 break;
825 }
826
827 case DBType::MYSQL: {
828 // DEBUG
829 OPENTREP_LOG_DEBUG ("Create the indices for the MySQL database");
830
831 try {
832
845
846 ioSociSession
847 << "alter table optd_por add unique index optd_por_pk (pk asc);";
848 ioSociSession
849 << "alter table optd_por add index optd_por_iata_code (iata_code asc);";
850 ioSociSession
851 << "alter table optd_por add index optd_por_iata_date (iata_code asc, date_from asc, date_until asc);";
852 ioSociSession
853 << "alter table optd_por add index optd_por_icao_code (icao_code asc);";
854 ioSociSession
855 << "alter table optd_por add index optd_por_geonameid (geoname_id asc);";
856 ioSociSession
857 << "alter table optd_por add index optd_por_unlocode_code (unlocode_code asc);";
858 ioSociSession
859 << "alter table optd_por add index optd_por_uic_code (uic_code asc);";
860
861 } catch (std::exception const& lException) {
862 std::ostringstream errorStr;
863 errorStr << "Error when trying to create MySQL/MariaDB indices: "
864 << lException.what();
865 OPENTREP_LOG_ERROR (errorStr.str());
866 throw SQLDatabaseIndexCreationException (errorStr.str());
867 }
868
869 // DEBUG
870 OPENTREP_LOG_DEBUG ("The indices have been created "
871 "for the MySQL/MariaDB database");
872
873 break;
874 }
875
876 case DBType::NODB: {
877 // Do nothing
878 break;
879 }
880
881 default: {
882 std::ostringstream errorStr;
883 errorStr << "Error: the '" << lDBName
884 << "' SQL database type is not supported";
885 OPENTREP_LOG_ERROR (errorStr.str());
886 throw SQLDatabaseIndexCreationException (errorStr.str());
887 break;
888 }
889 }
890 }
891
892 // //////////////////////////////////////////////////////////////////////
893 std::string DBManager::
894 prepareSelectAllBlobStatement (soci::session& ioSociSession,
895 soci::statement& ioSelectStatement) {
896 std::string oSerialisedPlaceStr;
897
898 try {
899
900 // Instanciate a SQL statement (no request is performed at that stage)
904
905 ioSelectStatement = (ioSociSession.prepare
906 << "select serialised_place from optd_por",
907 soci::into (oSerialisedPlaceStr));
908
909 // Execute the SQL query
910 ioSelectStatement.execute();
911
912 } catch (std::exception const& lException) {
913 std::ostringstream errorStr;
914 errorStr
915 << "Error in the 'select serialised_place from optd_por' SQL request: "
916 << lException.what();
917 OPENTREP_LOG_ERROR (errorStr.str());
918 throw SQLDatabaseException (errorStr.str());
919 }
920
921 //
922 return oSerialisedPlaceStr;
923 }
924
925 // //////////////////////////////////////////////////////////////////////
926 void DBManager::
927 prepareSelectBlobOnIataCodeStatement (soci::session& ioSociSession,
928 soci::statement& ioSelectStatement,
929 const std::string& iIataCode,
930 std::string& ioSerialisedPlaceStr) {
931
932 try {
933
934 // Instanciate a SQL statement (no request is performed at that stage)
938 ioSelectStatement = (ioSociSession.prepare
939 << "select serialised_place from optd_por "
940 << "where iata_code = :place_iata_code",
941 soci::use (iIataCode),
942 soci::into (ioSerialisedPlaceStr));
943
944 // Execute the SQL query
945 ioSelectStatement.execute();
946
947 } catch (std::exception const& lException) {
948 std::ostringstream errorStr;
949 errorStr
950 << "Error in the 'select serialised_place from optd_por' SQL request: "
951 << lException.what();
952 OPENTREP_LOG_ERROR (errorStr.str());
953 throw SQLDatabaseException (errorStr.str());
954 }
955 }
956
957 // //////////////////////////////////////////////////////////////////////
958 void DBManager::
959 prepareSelectBlobOnIcaoCodeStatement (soci::session& ioSociSession,
960 soci::statement& ioSelectStatement,
961 const std::string& iIcaoCode,
962 std::string& ioSerialisedPlaceStr) {
963
964 try {
965
966 // Instanciate a SQL statement (no request is performed at that stage)
970 ioSelectStatement = (ioSociSession.prepare
971 << "select serialised_place from optd_por "
972 << "where icao_code = :place_icao_code",
973 soci::use (iIcaoCode),
974 soci::into (ioSerialisedPlaceStr));
975
976 // Execute the SQL query
977 ioSelectStatement.execute();
978
979 } catch (std::exception const& lException) {
980 std::ostringstream errorStr;
981 errorStr
982 << "Error in the 'select serialised_place from optd_por' SQL request: "
983 << lException.what();
984 OPENTREP_LOG_ERROR (errorStr.str());
985 throw SQLDatabaseException (errorStr.str());
986 }
987 }
988
989 // //////////////////////////////////////////////////////////////////////
990 void DBManager::
991 prepareSelectBlobOnFaaCodeStatement (soci::session& ioSociSession,
992 soci::statement& ioSelectStatement,
993 const std::string& iFaaCode,
994 std::string& ioSerialisedPlaceStr) {
995
996 try {
997
998 // Instanciate a SQL statement (no request is performed at that stage)
1002 ioSelectStatement = (ioSociSession.prepare
1003 << "select serialised_place from optd_por "
1004 << "where faa_code = :place_faa_code",
1005 soci::use (iFaaCode),
1006 soci::into (ioSerialisedPlaceStr));
1007
1008 // Execute the SQL query
1009 ioSelectStatement.execute();
1010
1011 } catch (std::exception const& lException) {
1012 std::ostringstream errorStr;
1013 errorStr
1014 << "Error in the 'select serialised_place from optd_por' SQL request: "
1015 << lException.what();
1016 OPENTREP_LOG_ERROR (errorStr.str());
1017 throw SQLDatabaseException (errorStr.str());
1018 }
1019 }
1020
1021 // //////////////////////////////////////////////////////////////////////
1022 void DBManager::
1023 prepareSelectBlobOnUNLOCodeStatement (soci::session& ioSociSession,
1024 soci::statement& ioSelectStatement,
1025 const std::string& iUNLOCode,
1026 std::string& ioSerialisedPlaceStr) {
1027
1028 try {
1029
1030 // Instanciate a SQL statement (no request is performed at that stage)
1034 ioSelectStatement = (ioSociSession.prepare
1035 << "select serialised_place from optd_por "
1036 << "where unlocode_code = :place_unlocode_code",
1037 soci::use (iUNLOCode),
1038 soci::into (ioSerialisedPlaceStr));
1039
1040 // Execute the SQL query
1041 ioSelectStatement.execute();
1042
1043 } catch (std::exception const& lException) {
1044 std::ostringstream errorStr;
1045 errorStr
1046 << "Error in the 'select serialised_place from optd_por' SQL request: "
1047 << lException.what();
1048 OPENTREP_LOG_ERROR (errorStr.str());
1049 throw SQLDatabaseException (errorStr.str());
1050 }
1051 }
1052
1053 // //////////////////////////////////////////////////////////////////////
1054 void DBManager::
1055 prepareSelectBlobOnUICCodeStatement (soci::session& ioSociSession,
1056 soci::statement& ioSelectStatement,
1057 const UICCode_T& iUICCode,
1058 std::string& ioSerialisedPlaceStr) {
1059
1060 try {
1061
1062 // Instanciate a SQL statement (no request is performed at that stage)
1066 ioSelectStatement = (ioSociSession.prepare
1067 << "select serialised_place from optd_por "
1068 << "where uic_code = :place_uic_code",
1069 soci::use (iUICCode),
1070 soci::into (ioSerialisedPlaceStr));
1071
1072 // Execute the SQL query
1073 ioSelectStatement.execute();
1074
1075 } catch (std::exception const& lException) {
1076 std::ostringstream errorStr;
1077 errorStr
1078 << "Error in the 'select serialised_place from optd_por' SQL request: "
1079 << lException.what();
1080 OPENTREP_LOG_ERROR (errorStr.str());
1081 throw SQLDatabaseException (errorStr.str());
1082 }
1083 }
1084
1085 // //////////////////////////////////////////////////////////////////////
1086 void DBManager::
1087 prepareSelectBlobOnPlaceGeoIDStatement (soci::session& ioSociSession,
1088 soci::statement& ioSelectStatement,
1089 const GeonamesID_T& iGeonameID,
1090 std::string& ioSerialisedPlaceStr) {
1091
1092 try {
1093
1094 // Instanciate a SQL statement (no request is performed at that stage)
1098 ioSelectStatement = (ioSociSession.prepare
1099 << "select serialised_place from optd_por "
1100 << "where geoname_id = :place_geoname_id",
1101 soci::use (iGeonameID),
1102 soci::into (ioSerialisedPlaceStr));
1103
1104 // Execute the SQL query
1105 ioSelectStatement.execute();
1106
1107 } catch (std::exception const& lException) {
1108 std::ostringstream errorStr;
1109 errorStr
1110 << "Error in the 'select serialised_place from optd_por' SQL request: "
1111 << lException.what();
1112 OPENTREP_LOG_ERROR (errorStr.str());
1113 throw SQLDatabaseException (errorStr.str());
1114 }
1115 }
1116
1117 // //////////////////////////////////////////////////////////////////////
1118 bool DBManager::iterateOnStatement (soci::statement& ioStatement,
1119 const std::string& iSerialisedPlaceStr) {
1120 bool hasStillData = false;
1121
1122 try {
1123
1124 // Retrieve the next row of Place object
1125 hasStillData = ioStatement.fetch();
1126
1127 } catch (std::exception const& lException) {
1128 std::ostringstream errorStr;
1129 errorStr << "Error when iterating on the SQL fetch: " << lException.what();
1130 errorStr << ". The current place is: " << iSerialisedPlaceStr;
1131 OPENTREP_LOG_ERROR (errorStr.str());
1132 throw SQLDatabaseException (errorStr.str());
1133 }
1134
1135 return hasStillData;
1136 }
1137
1138 // //////////////////////////////////////////////////////////////////////
1139 void DBManager::insertPlaceInDB (soci::session& ioSociSession,
1140 const Place& iPlace) {
1141
1142 try {
1143
1144 // Begin a transaction on the database
1145 ioSociSession.begin();
1146
1147 // Instanciate a SQL statement (no request is performed at that stage)
1148 const LocationKey& lLocationKey = iPlace.getKey();
1149 const std::string lPK (lLocationKey.toString());
1150 const IATAType& lIataType = iPlace.getIataType();
1151 const std::string lLocationType (lIataType.getTypeAsString());
1152 const std::string lIataCode (iPlace.getIataCode());
1153 const std::string lIcaoCode (iPlace.getIcaoCode());
1154 const std::string lFaaCode (iPlace.getFaaCode());
1155 const std::string lIsGeonames ((iPlace.isGeonames())?"Y":"N");
1156 const std::string lGeonameID =
1157 boost::lexical_cast<std::string> (iPlace.getGeonamesID());
1158 const std::string lEnvID =
1159 boost::lexical_cast<std::string> (iPlace.getEnvelopeID());
1160 const std::string lDateFrom =
1161 boost::gregorian::to_iso_extended_string (iPlace.getDateFrom());
1162 const std::string lDateEnd =
1163 boost::gregorian::to_iso_extended_string (iPlace.getDateEnd());
1164 const std::string lRawDataString (iPlace.getRawDataString());
1165
1190 const UNLOCodeList_T& lUNLOCodeList = iPlace.getUNLOCodeList();
1191 std::string lUNLOCodeStr ("");
1192 if (lUNLOCodeList.empty() == false) {
1193 const UNLOCode_T& lUNLOCode = lUNLOCodeList.front();
1194 lUNLOCodeStr = static_cast<const std::string> (lUNLOCode);
1195 }
1196
1201 const UICCodeList_T& lUICCodeList = iPlace.getUICCodeList();
1202 UICCode_T lUICCodeInt = 0;
1203 if (lUICCodeList.empty() == false) {
1204 const UICCode_T& lUICCode = lUICCodeList.front();
1205 lUICCodeInt = static_cast<const UICCode_T> (lUICCode);
1206 }
1207
1208
1209 // DEBUG
1210 /*
1211 std::ostringstream oStr;
1212 oStr << "insert into optd_por values (" << lPK << ", ";
1213 oStr << lLocationType << ", ";
1214 oStr << lIataCode << ", " << lIcaoCode << ", " << lFaaCode << ", ";
1215 oStr << lUNLOCode << ", ";
1216 oStr << lUICCode << ", ";
1217 oStr << lIsGeonames << ", " << lGeonameID << ", ";
1218 oStr << lEnvID << ", " << lDateFrom << ", " << lDateEnd << ", ";
1219 oStr << lRawDataString << ")";
1220 OPENTREP_LOG_DEBUG ("Full SQL statement: '" << oStr.str() << "'");
1221 */
1222
1223 ioSociSession << "insert into optd_por values (:pk, "
1224 << ":location_type, :iata_code, :icao_code, :faa_code, "
1225 << ":unlocode_code, :uic_code, "
1226 << ":is_geonames, :geoname_id, "
1227 << ":envelope_id, :date_from, :date_until, "
1228 << ":serialised_place)",
1229 soci::use (lPK), soci::use (lLocationType), soci::use (lIataCode),
1230 soci::use (lIcaoCode), soci::use (lFaaCode),
1231 soci::use (lUNLOCodeStr), soci::use (lUICCodeInt),
1232 soci::use (lIsGeonames), soci::use (lGeonameID),
1233 soci::use (lEnvID), soci::use (lDateFrom), soci::use (lDateEnd),
1234 soci::use (lRawDataString);
1235
1236 // Commit the transaction on the database
1237 ioSociSession.commit();
1238
1239 // Debug
1240 // OPENTREP_LOG_DEBUG ("[" << lDocID << "] " << iPlace);
1241
1242 } catch (std::exception const& lException) {
1243 std::ostringstream errorStr;
1244 errorStr << "Error when updating " << iPlace.toString() << ": "
1245 << lException.what();
1246 OPENTREP_LOG_ERROR (errorStr.str());
1247 throw SQLDatabaseException (errorStr.str());
1248 }
1249 }
1250
1251 // //////////////////////////////////////////////////////////////////////
1252 void DBManager::updatePlaceInDB (soci::session& ioSociSession,
1253 const Place& iPlace) {
1254
1255 try {
1256
1257 // Begin a transaction on the database
1258 ioSociSession.begin();
1259
1260 // Instanciate a SQL statement (no request is performed at that stage)
1261 XapianDocID_T lDocID;
1262 std::string lIataCode;
1263 soci::statement lUpdateStatement =
1264 (ioSociSession.prepare
1265 << "update place_details "
1266 << "set xapian_docid = :xapian_docid "
1267 << "where iata_code = :iata_code",
1268 soci::use (lDocID), soci::use (lIataCode));
1269
1270 // Execute the SQL query
1271 lDocID = iPlace.getDocID();
1272 lIataCode = iPlace.getIataCode();
1273 lUpdateStatement.execute (true);
1274
1275 // Commit the transaction on the database
1276 ioSociSession.commit();
1277
1278 // Debug
1279 // OPENTREP_LOG_DEBUG ("[" << lDocID << "] " << iPlace);
1280
1281 } catch (std::exception const& lException) {
1282 std::ostringstream errorStr;
1283 errorStr << "Error when updating " << iPlace.toString() << ": "
1284 << lException.what();
1285 OPENTREP_LOG_ERROR (errorStr.str());
1286 throw SQLDatabaseException (errorStr.str());
1287 }
1288 }
1289
1290 // //////////////////////////////////////////////////////////////////////
1291 NbOfDBEntries_T DBManager::displayCount (soci::session& ioSociSession) {
1292 NbOfDBEntries_T oNbOfEntries = 0;
1293
1294 try {
1295
1301
1302 ioSociSession << "select count(1) from optd_por;", soci::into(oNbOfEntries);
1303
1304 } catch (std::exception const& lException) {
1305 std::ostringstream errorStr;
1306 errorStr
1307 << "Error when trying to count the number of rows in the optd_por table: "
1308 << lException.what();
1309 OPENTREP_LOG_ERROR (errorStr.str());
1310 throw SQLDatabaseIndexCreationException (errorStr.str());
1311 }
1312
1313 return oNbOfEntries;
1314 }
1315
1316 // //////////////////////////////////////////////////////////////////////
1317 NbOfDBEntries_T DBManager::displayAll (soci::session& ioSociSession) {
1318 NbOfDBEntries_T oNbOfEntries = 0;
1319
1320 try {
1321
1322 // Prepare the SQL request corresponding to the select statement
1323 soci::statement lSelectStatement (ioSociSession);
1324 std::string lPlace =
1326 lSelectStatement);
1327
1332 bool hasStillData = true;
1333 while (hasStillData == true) {
1334 hasStillData = iterateOnStatement (lSelectStatement, lPlace);
1335
1336 // It is enough to have (at least) one database retrieved row
1337 if (hasStillData == true) {
1338 ++oNbOfEntries;
1339
1340 // Debug
1341 OPENTREP_LOG_DEBUG ("[" << oNbOfEntries << "] " << lPlace);
1342 }
1343 }
1344
1345 } catch (std::exception const& lException) {
1346 std::ostringstream errorStr;
1347 errorStr << "Error when trying to retrieve " << oNbOfEntries
1348 << "-th row from the SQL database: " << lException.what();
1349 OPENTREP_LOG_ERROR (errorStr.str());
1350 throw SQLDatabaseException (errorStr.str());
1351 }
1352
1353 return oNbOfEntries;
1354 }
1355
1356 // //////////////////////////////////////////////////////////////////////
1357 NbOfDBEntries_T DBManager::getPORByIATACode (soci::session& ioSociSession,
1358 const IATACode_T& iIataCode,
1359 LocationList_T& ioLocationList,
1360 const bool iUniqueEntry) {
1361 NbOfDBEntries_T oNbOfEntries = 0;
1362 LocationList_T lLocationList;
1363
1364 try {
1365
1366 // Convert the code into uppercase. That way, one can search for codes
1367 // irrespective of the case (knwing that codes are stored uppercase
1368 // in the database)
1369 const std::string& lCode = static_cast<const std::string&> (iIataCode);
1370 const std::string lCodeUpper = boost::algorithm::to_upper_copy (lCode);
1371
1372 // Prepare the SQL request corresponding to the select statement
1373 soci::statement lSelectStatement (ioSociSession);
1374 std::string lPlaceRawDataString;
1375 DBManager::prepareSelectBlobOnIataCodeStatement (ioSociSession,
1376 lSelectStatement,
1377 lCodeUpper,
1378 lPlaceRawDataString);
1379
1384 bool hasStillData = true;
1385 while (hasStillData == true) {
1386 hasStillData = iterateOnStatement (lSelectStatement,
1387 lPlaceRawDataString);
1388
1389 // DEBUG
1390 const std::string lFoundStr = hasStillData?"more; see below":"no more";
1391 OPENTREP_LOG_DEBUG ("Checked whether there are more locations "
1392 << "corresponding to '" << iIataCode
1393 << "' IATA code. Result: " << lFoundStr);
1394
1395 if (hasStillData == true) {
1396 //
1397 ++oNbOfEntries;
1398
1399 // Parse the POR details and create the corresponding
1400 // Location structure
1401 const RawDataString_T lPlaceRawData (lPlaceRawDataString);
1402 Location lLocation = Result::retrieveLocation (lPlaceRawData);
1403 lLocation.setCorrectedKeywords (iIataCode);
1404
1405 // Add the new found location to the list
1406 lLocationList.push_back (lLocation);
1407
1408 // Debug
1409 OPENTREP_LOG_DEBUG ("[" << oNbOfEntries << "] " << lLocation);
1410 }
1411 }
1412
1413 } catch (std::exception const& lException) {
1414 std::ostringstream errorStr;
1415 errorStr << "Error when trying to retrieve a POR for " << iIataCode
1416 << " from the SQL database: " << lException.what();
1417 OPENTREP_LOG_ERROR (errorStr.str());
1418 throw SQLDatabaseException (errorStr.str());
1419 }
1420
1421 // Add the just retrieved Location structure(s) to the list given
1422 // as parameter
1423 const Location* lHighestPRLocation_ptr = NULL;
1424 PageRank_T lHighestPRValue = 0.0;
1425 for (LocationList_T::const_iterator itLoc = lLocationList.begin();
1426 itLoc != lLocationList.end(); ++itLoc) {
1427 const Location& lLocation = *itLoc;
1428 const PageRank_T& lPRValue = lLocation.getPageRank();
1429
1430 // Store (a pointer on) the Location structure with the highest Page Rank.
1431 // Normally, when there is no PageRank value, the field should be empty
1432 // (empty string). In some rare cases, actually when OPTD is buggy,
1433 // the PageRank value may be zero. While it is a bug from OPTD, there is
1434 // no reason it should trigger a bug from OpenTREP in turn. So, rather
1435 // then ignoring any POR with zero PageRank value, rather the first one
1436 // is (randomly) selected
1437 if (lPRValue >= lHighestPRValue) {
1438 lHighestPRLocation_ptr = &lLocation;
1439 lHighestPRValue = lPRValue;
1440 }
1441
1442 // Add the Location structure now, only when a unique solution
1443 // is not expected
1444 if (iUniqueEntry == false) {
1445 ioLocationList.push_back (lLocation);
1446 }
1447 }
1448
1449 // Add the Location structure with the highest Page Rank value
1450 if (iUniqueEntry == true && lHighestPRLocation_ptr != NULL) {
1451 assert (lHighestPRLocation_ptr != NULL);
1452 ioLocationList.push_back (*lHighestPRLocation_ptr);
1453
1454 // DEBUG
1455 OPENTREP_LOG_DEBUG("Kept the location with the highest PageRank value ("
1456 << lHighestPRValue << ") for '" << iIataCode
1457 << "' IATA code: " << lHighestPRLocation_ptr->getKey());
1458 }
1459
1460 // Make the number of retrieved locations consistent with the unicity
1461 // requirement (if set)
1462 if (oNbOfEntries > 0 && iUniqueEntry == true) {
1463 oNbOfEntries = 1;
1464 }
1465
1466 //
1467 return oNbOfEntries;
1468 }
1469
1470 // //////////////////////////////////////////////////////////////////////
1471 NbOfDBEntries_T DBManager::getPORByICAOCode (soci::session& ioSociSession,
1472 const ICAOCode_T& iIcaoCode,
1473 LocationList_T& ioLocationList) {
1474 NbOfDBEntries_T oNbOfEntries = 0;
1475
1476 try {
1477
1478 // Convert the code into uppercase. That way, one can search for codes
1479 // irrespective of the case (knwing that codes are stored uppercase
1480 // in the database)
1481 const std::string& lCode = static_cast<const std::string&> (iIcaoCode);
1482 const std::string lCodeUpper = boost::algorithm::to_upper_copy (lCode);
1483
1484 // Prepare the SQL request corresponding to the select statement
1485 soci::statement lSelectStatement (ioSociSession);
1486 std::string lPlaceRawDataString;
1487 DBManager::prepareSelectBlobOnIcaoCodeStatement (ioSociSession,
1488 lSelectStatement,
1489 lCodeUpper,
1490 lPlaceRawDataString);
1491
1496 bool hasStillData = true;
1497 while (hasStillData == true) {
1498 hasStillData = iterateOnStatement (lSelectStatement,
1499 lPlaceRawDataString);
1500
1501 // DEBUG
1502 const std::string lFoundStr = hasStillData?"Yes":"No";
1503 OPENTREP_LOG_DEBUG ("Checked locations corresponding to "
1504 << iIcaoCode << " ICAO code. Found: " << lFoundStr);
1505
1506 if (hasStillData == true) {
1507 //
1508 ++oNbOfEntries;
1509
1510 // Parse the POR details and create the corresponding
1511 // Location structure
1512 const RawDataString_T lPlaceRawData (lPlaceRawDataString);
1513 Location lLocation = Result::retrieveLocation (lPlaceRawData);
1514 lLocation.setCorrectedKeywords (iIcaoCode);
1515
1516 // Add the new found location to the list
1517 ioLocationList.push_back (lLocation);
1518
1519 // Debug
1520 OPENTREP_LOG_DEBUG ("[" << oNbOfEntries << "] " << lLocation);
1521 }
1522 }
1523
1524 } catch (std::exception const& lException) {
1525 std::ostringstream errorStr;
1526 errorStr << "Error when trying to retrieve a POR for " << iIcaoCode
1527 << " from the SQL database: " << lException.what();
1528 OPENTREP_LOG_ERROR (errorStr.str());
1529 throw SQLDatabaseException (errorStr.str());
1530 }
1531
1532 //
1533 return oNbOfEntries;
1534 }
1535
1536 // //////////////////////////////////////////////////////////////////////
1537 NbOfDBEntries_T DBManager::getPORByFAACode (soci::session& ioSociSession,
1538 const FAACode_T& iFaaCode,
1539 LocationList_T& ioLocationList) {
1540 NbOfDBEntries_T oNbOfEntries = 0;
1541
1542 try {
1543
1544 // Convert the code into uppercase. That way, one can search for codes
1545 // irrespective of the case (knwing that codes are stored uppercase
1546 // in the database)
1547 const std::string& lCode = static_cast<const std::string&> (iFaaCode);
1548 const std::string lCodeUpper = boost::algorithm::to_upper_copy (lCode);
1549
1550 // Prepare the SQL request corresponding to the select statement
1551 soci::statement lSelectStatement (ioSociSession);
1552 std::string lPlaceRawDataString;
1553 DBManager::prepareSelectBlobOnFaaCodeStatement (ioSociSession,
1554 lSelectStatement,
1555 lCodeUpper,
1556 lPlaceRawDataString);
1557
1562 bool hasStillData = true;
1563 while (hasStillData == true) {
1564 hasStillData = iterateOnStatement (lSelectStatement,
1565 lPlaceRawDataString);
1566
1567 // DEBUG
1568 const std::string lFoundStr = hasStillData?"Yes":"No";
1569 OPENTREP_LOG_DEBUG ("Checked locations corresponding to "
1570 << iFaaCode << " FAA code. Found: " << lFoundStr);
1571
1572 if (hasStillData == true) {
1573 //
1574 ++oNbOfEntries;
1575
1576 // Parse the POR details and create the corresponding
1577 // Location structure
1578 const RawDataString_T lPlaceRawData (lPlaceRawDataString);
1579 Location lLocation = Result::retrieveLocation (lPlaceRawData);
1580 lLocation.setCorrectedKeywords (iFaaCode);
1581
1582 // Add the new found location to the list
1583 ioLocationList.push_back (lLocation);
1584
1585 // Debug
1586 OPENTREP_LOG_DEBUG ("[" << oNbOfEntries << "] " << lLocation);
1587 }
1588 }
1589
1590 } catch (std::exception const& lException) {
1591 std::ostringstream errorStr;
1592 errorStr << "Error when trying to retrieve a POR for " << iFaaCode
1593 << " from the SQL database: " << lException.what();
1594 OPENTREP_LOG_ERROR (errorStr.str());
1595 throw SQLDatabaseException (errorStr.str());
1596 }
1597
1598 //
1599 return oNbOfEntries;
1600 }
1601
1602 // //////////////////////////////////////////////////////////////////////
1603 NbOfDBEntries_T DBManager::getPORByUNLOCode (soci::session& ioSociSession,
1604 const UNLOCode_T& iUNLOCode,
1605 LocationList_T& ioLocationList,
1606 const bool iUniqueEntry) {
1607 NbOfDBEntries_T oNbOfEntries = 0;
1608 LocationList_T lLocationList;
1609
1610 try {
1611
1612 // Convert the code into uppercase. That way, one can search for codes
1613 // irrespective of the case (knwing that codes are stored uppercase
1614 // in the database)
1615 const std::string& lCode = static_cast<const std::string&> (iUNLOCode);
1616 const std::string lCodeUpper = boost::algorithm::to_upper_copy (lCode);
1617
1618 // Prepare the SQL request corresponding to the select statement
1619 soci::statement lSelectStatement (ioSociSession);
1620 std::string lPlaceRawDataString;
1621 DBManager::prepareSelectBlobOnUNLOCodeStatement (ioSociSession,
1622 lSelectStatement,
1623 lCodeUpper,
1624 lPlaceRawDataString);
1625
1630 bool hasStillData = true;
1631 while (hasStillData == true) {
1632 hasStillData = iterateOnStatement (lSelectStatement,
1633 lPlaceRawDataString);
1634
1635 // DEBUG
1636 const std::string lFoundStr = hasStillData?"Yes":"No";
1637 OPENTREP_LOG_DEBUG ("Checked locations corresponding to "
1638 << iUNLOCode << " UN/LOCODE code. Found: "
1639 << lFoundStr);
1640
1641 if (hasStillData == true) {
1642 //
1643 ++oNbOfEntries;
1644
1645 // Parse the POR details and create the corresponding
1646 // Location structure
1647 const RawDataString_T lPlaceRawData (lPlaceRawDataString);
1648 Location lLocation = Result::retrieveLocation (lPlaceRawData);
1649 lLocation.setCorrectedKeywords (iUNLOCode);
1650
1651 // Add the new found location to the list
1652 lLocationList.push_back (lLocation);
1653
1654 // Debug
1655 OPENTREP_LOG_DEBUG ("[" << oNbOfEntries << "] " << lLocation);
1656 }
1657 }
1658
1659 } catch (std::exception const& lException) {
1660 std::ostringstream errorStr;
1661 errorStr << "Error when trying to retrieve a POR for " << iUNLOCode
1662 << " from the SQL database: " << lException.what();
1663 OPENTREP_LOG_ERROR (errorStr.str());
1664 throw SQLDatabaseException (errorStr.str());
1665 }
1666
1667 // Add the just retrieved Location structure(s) to the list given
1668 // as parameter
1669 const Location* lHighestPRLocation_ptr = NULL;
1670 PageRank_T lHighestPRValue = 0.0;
1671 for (LocationList_T::const_iterator itLoc = lLocationList.begin();
1672 itLoc != lLocationList.end(); ++itLoc) {
1673 const Location& lLocation = *itLoc;
1674 const PageRank_T& lPRValue = lLocation.getPageRank();
1675
1676 // Store (a pointer on) the Location structure with the highest Page Rank
1677 if (lPRValue > lHighestPRValue) {
1678 lHighestPRLocation_ptr = &lLocation;
1679 lHighestPRValue = lPRValue;
1680 }
1681
1682 // Add the Location structure now, only when
1683 if (iUniqueEntry == false) {
1684 ioLocationList.push_back (lLocation);
1685 }
1686 }
1687
1688 // Add the Location structure with the highest Page Rank value
1689 if (iUniqueEntry == true && lHighestPRLocation_ptr != NULL) {
1690 assert (lHighestPRLocation_ptr != NULL);
1691 ioLocationList.push_back (*lHighestPRLocation_ptr);
1692
1693 // DEBUG
1694 OPENTREP_LOG_DEBUG("Kept the location with the highest PageRank value ("
1695 << lHighestPRValue << ") for '" << iUNLOCode
1696 << "' IATA code: " << lHighestPRLocation_ptr->getKey());
1697 }
1698
1699 // Make the number of retrieved locations consistent with the unicity
1700 // requirement (if set)
1701 if (oNbOfEntries > 0 && iUniqueEntry == true) {
1702 oNbOfEntries = 1;
1703 }
1704
1705 //
1706 return oNbOfEntries;
1707 }
1708
1709 // //////////////////////////////////////////////////////////////////////
1710 NbOfDBEntries_T DBManager::getPORByUICCode (soci::session& ioSociSession,
1711 const UICCode_T& iUICCode,
1712 LocationList_T& ioLocationList) {
1713 NbOfDBEntries_T oNbOfEntries = 0;
1714
1715 try {
1716
1717 // Prepare the SQL request corresponding to the select statement
1718 soci::statement lSelectStatement (ioSociSession);
1719 std::string lPlaceRawDataString;
1720 DBManager::prepareSelectBlobOnUICCodeStatement (ioSociSession,
1721 lSelectStatement,
1722 iUICCode,
1723 lPlaceRawDataString);
1724
1729 bool hasStillData = true;
1730 while (hasStillData == true) {
1731 hasStillData = iterateOnStatement (lSelectStatement,
1732 lPlaceRawDataString);
1733
1734 // DEBUG
1735 const std::string lFoundStr = hasStillData?"Yes":"No";
1736 OPENTREP_LOG_DEBUG ("Checked locations corresponding to "
1737 << iUICCode << " UIC code. Found: "
1738 << lFoundStr);
1739
1740 if (hasStillData == true) {
1741 //
1742 ++oNbOfEntries;
1743
1744 // Parse the POR details and create the corresponding
1745 // Location structure
1746 const RawDataString_T lPlaceRawData (lPlaceRawDataString);
1747 Location lLocation = Result::retrieveLocation (lPlaceRawData);
1748 const std::string lUICCodeStr =
1749 boost::lexical_cast<std::string> (iUICCode);
1750 lLocation.setCorrectedKeywords (lUICCodeStr);
1751
1752 // Add the new found location to the list
1753 ioLocationList.push_back (lLocation);
1754
1755 // Debug
1756 OPENTREP_LOG_DEBUG ("[" << oNbOfEntries << "] " << lLocation);
1757 }
1758 }
1759
1760 } catch (std::exception const& lException) {
1761 std::ostringstream errorStr;
1762 errorStr << "Error when trying to retrieve a POR for " << iUICCode
1763 << " from the SQL database: " << lException.what();
1764 OPENTREP_LOG_ERROR (errorStr.str());
1765 throw SQLDatabaseException (errorStr.str());
1766 }
1767
1768 //
1769 return oNbOfEntries;
1770 }
1771
1772 // //////////////////////////////////////////////////////////////////////
1773 NbOfDBEntries_T DBManager::getPORByGeonameID (soci::session& ioSociSession,
1774 const GeonamesID_T& iGeonameID,
1775 LocationList_T& ioLocationList) {
1776 NbOfDBEntries_T oNbOfEntries = 0;
1777
1778 try {
1779
1780 // Prepare the SQL request corresponding to the select statement
1781 soci::statement lSelectStatement (ioSociSession);
1782 std::string lPlaceRawDataString;
1783 DBManager::prepareSelectBlobOnPlaceGeoIDStatement (ioSociSession,
1784 lSelectStatement,
1785 iGeonameID,
1786 lPlaceRawDataString);
1787
1792 bool hasStillData = true;
1793 while (hasStillData == true) {
1794 hasStillData = iterateOnStatement (lSelectStatement,
1795 lPlaceRawDataString);
1796
1797 // DEBUG
1798 const std::string lFoundStr = hasStillData?"Yes":"No";
1799 OPENTREP_LOG_DEBUG ("Checked locations corresponding to "
1800 << iGeonameID<< " Geonames ID. Found: "<< lFoundStr);
1801
1802 if (hasStillData == true) {
1803 //
1804 ++oNbOfEntries;
1805
1806 // Parse the POR details and create the corresponding
1807 // Location structure
1808 const RawDataString_T lPlaceRawData (lPlaceRawDataString);
1809 Location lLocation = Result::retrieveLocation (lPlaceRawData);
1810 const std::string lGeonamesIDStr =
1811 boost::lexical_cast<std::string> (iGeonameID);
1812 lLocation.setCorrectedKeywords (lGeonamesIDStr);
1813
1814 // Add the new found location to the list
1815 ioLocationList.push_back (lLocation);
1816
1817 // Debug
1818 OPENTREP_LOG_DEBUG ("[" << oNbOfEntries << "] " << lLocation);
1819 }
1820 }
1821
1822 } catch (std::exception const& lException) {
1823 std::ostringstream errorStr;
1824 errorStr << "Error when trying to retrieve a POR for " << iGeonameID
1825 << " from the SQL database: " << lException.what();
1826 OPENTREP_LOG_ERROR (errorStr.str());
1827 throw SQLDatabaseException (errorStr.str());
1828 }
1829
1830 //
1831 return oNbOfEntries;
1832 }
1833
1834}
#define OPENTREP_LOG_ERROR(iToBeLogged)
Definition Logger.hpp:24
#define OPENTREP_LOG_DEBUG(iToBeLogged)
Definition Logger.hpp:33
static void terminateSQLDBSession(const DBType &, const SQLDBConnectionString_T &, soci::session &)
static void createSQLDBTables(soci::session &)
static std::string prepareSelectAllBlobStatement(soci::session &, soci::statement &)
static NbOfDBEntries_T getPORByUICCode(soci::session &, const UICCode_T &, LocationList_T &)
static NbOfDBEntries_T getPORByICAOCode(soci::session &, const ICAOCode_T &, LocationList_T &)
static soci::session * initSQLDBSession(const DBType &, const SQLDBConnectionString_T &)
static NbOfDBEntries_T getPORByFAACode(soci::session &, const FAACode_T &, LocationList_T &)
static void createSQLDBIndexes(soci::session &)
static NbOfDBEntries_T displayCount(soci::session &)
static NbOfDBEntries_T displayAll(soci::session &)
static NbOfDBEntries_T getPORByUNLOCode(soci::session &, const UNLOCode_T &, LocationList_T &, const bool iUniqueEntry)
static NbOfDBEntries_T getPORByGeonameID(soci::session &, const GeonamesID_T &, LocationList_T &)
static NbOfDBEntries_T getPORByIATACode(soci::session &, const IATACode_T &, LocationList_T &, const bool iUniqueEntry)
static void updatePlaceInDB(soci::session &, const Place &)
static bool iterateOnStatement(soci::statement &, const std::string &)
static bool createSQLDBUser(const DBType &, const SQLDBConnectionString_T &, const DeploymentNumber_T &)
static void insertPlaceInDB(soci::session &, const Place &)
static bool checkSQLiteDirectory(const std::string &iSQLDBConnStr)
Class modelling a place/POR (point of reference).
Definition Place.hpp:29
const IsGeonames_T & isGeonames() const
Definition Place.hpp:87
const ICAOCode_T & getIcaoCode() const
Definition Place.hpp:94
const RawDataString_T & getRawDataString() const
Definition Place.hpp:467
const FAACode_T & getFaaCode() const
Definition Place.hpp:101
const Date_T & getDateEnd() const
Definition Place.hpp:158
const GeonamesID_T & getGeonamesID() const
Definition Place.hpp:80
const XapianDocID_T & getDocID() const
Definition Place.hpp:474
const IATACode_T & getIataCode() const
Definition Place.hpp:66
const Date_T & getDateFrom() const
Definition Place.hpp:151
const EnvelopeID_T & getEnvelopeID() const
Definition Place.hpp:144
const UNLOCodeList_T & getUNLOCodeList() const
Definition Place.hpp:108
std::string toString() const
Definition Place.cpp:85
const IATAType & getIataType() const
Definition Place.hpp:73
const LocationKey & getKey() const
Definition Place.hpp:59
const UICCodeList_T & getUICCodeList() const
Definition Place.hpp:115
static Location retrieveLocation(const Xapian::Document &)
Definition Result.cpp:272
unsigned int UICCode_T
bool createSQLDBUserOnPG(const SQLDBConnectionString_T &iSQLDBConnStr, const DeploymentNumber_T &iDeploymentNumber)
bool createSQLDBUserOnMySQL(const SQLDBConnectionString_T &iSQLDBConnStr, const DeploymentNumber_T &iDeploymentNumber)
Definition DBManager.cpp:88
unsigned int NbOfDBEntries_T
const std::string DEFAULT_OPENTREP_MYSQL_DB_DBNAME
const std::string DEFAULT_OPENTREP_MYSQL_DB_USER
double PageRank_T
const std::string DEFAULT_OPENTREP_MYSQL_DB_PASSWD
std::list< Location > LocationList_T
std::list< UICCode_T > UICCodeList_T
const std::string DEFAULT_OPENTREP_MYSQL_DB_HOST
std::list< UNLOCode_T > UNLOCodeList_T
const std::string DEFAULT_OPENTREP_PG_DB_USER
bool createSQLDBUserOnSQLite(const SQLDBConnectionString_T &iSQLDBConnStr, const DeploymentNumber_T &iDeploymentNumber)
Definition DBManager.cpp:35
unsigned short DeploymentNumber_T
unsigned int GeonamesID_T
const std::string DEFAULT_OPENTREP_PG_DB_DBNAME
unsigned int XapianDocID_T
Enumeration of database types.
Definition DBType.hpp:17
const std::string describe() const
Definition DBType.cpp:135
static EN_DBType getType(const char)
Definition DBType.cpp:35
Enumeration of place/location types with respect to their use for transportation purposes.
Definition IATAType.hpp:42
std::string getTypeAsString() const
Definition IATAType.cpp:174
Class modelling the primary key of a location/POR (point of reference).
std::string toString() const
Structure modelling a (geographical) location.
Definition Location.hpp:25
const LocationKey & getKey() const
Definition Location.hpp:31
const PageRank_T & getPageRank() const
Definition Location.hpp:354
void setCorrectedKeywords(const std::string &iCorrectedKeywords)
Definition Location.hpp:846