MythTV master
dbutil.cpp
Go to the documentation of this file.
1#include <climits>
2#include <cstdio>
3#include <cstdlib>
4#include <sys/stat.h>
5#include <sys/types.h>
6#include <unistd.h>
7
8#include <QDir>
9#include <QFile>
10#include <QRegularExpression>
11#include <QDateTime>
12#include <QSqlError>
13#include <QSqlRecord>
14
15#include "dbutil.h"
16#include "mythcorecontext.h"
17#include "storagegroup.h"
18#include "mythmiscutil.h"
19#include "mythdate.h"
20#include "mythdb.h"
21#include "mythdirs.h"
22#include "mythlogging.h"
23#include "mythsystemlegacy.h"
24#include "exitcodes.h"
25
26#define LOC QString("DBUtil: ")
27
28const int DBUtil::kUnknownVersionNumber = INT_MIN;
29
35{
36 if (m_versionString.isEmpty())
38 return m_versionString;
39}
40
53int DBUtil::CompareDBMSVersion(int major, int minor, int point)
54{
55 if (m_versionMajor < 0)
56 if (!ParseDBMSVersion())
58
59 int result = 0;
61 std::array<int,3> compareto {major, minor, point};
62 for (int i = 0; i < 3 && !result; i++)
63 {
64 if ((version[i] > -1) || (compareto[i] != 0))
65 result = version[i] - compareto[i];
66 }
67
68 return result;
69}
70
75{
76 const QStringList tables = GetTables();
77 const int size = tables.size();
78 // Usually there will be a single table called schemalock, but check for
79 // no tables, also, just in case.
80 return (((size == 1) && (tables.at(0).endsWith(".`schemalock`"))) ||
81 (size == 0));
82}
83
89{
90 QString backupStartTimeStr =
91 gCoreContext->GetSetting("BackupDBLastRunStart");
92 QString backupEndTimeStr = gCoreContext->GetSetting("BackupDBLastRunEnd");
93
94 if (backupStartTimeStr.isEmpty())
95 {
96 LOG(VB_DATABASE, LOG_ERR, "DBUtil::BackupInProgress(): No start time "
97 "found, database backup is not in progress.");
98 return false;
99 }
100
101 backupStartTimeStr.replace(" ", "T");
102
103 QDateTime backupStartTime = MythDate::fromString(backupStartTimeStr);
104 auto backupElapsed = MythDate::secsInPast(backupStartTime);
105
106 // No end time set
107 if (backupEndTimeStr.isEmpty())
108 {
109 // If DB Backup started less then 10 minutes ago, assume still running
110 if (backupElapsed < 10min)
111 {
112 LOG(VB_DATABASE, LOG_INFO,
113 QString("DBUtil::BackupInProgress(): Found "
114 "database backup start time of %1 which was %2 seconds "
115 "ago, therefore it appears the backup is still running.")
116 .arg(backupStartTimeStr)
117 .arg(backupElapsed.count()));
118 return true;
119 }
120 LOG(VB_DATABASE, LOG_ERR, QString("DBUtil::BackupInProgress(): "
121 "Database backup started at %1, but no end time was found. "
122 "The backup started %2 seconds ago and should have "
123 "finished by now therefore it appears it is not running .")
124 .arg(backupStartTimeStr)
125 .arg(backupElapsed.count()));
126 return false;
127 }
128
129 backupEndTimeStr.replace(" ", "T");
130
131 QDateTime backupEndTime = MythDate::fromString(backupEndTimeStr);
132
133 if (backupEndTime >= backupStartTime)
134 {
135 LOG(VB_DATABASE, LOG_ERR,
136 QString("DBUtil::BackupInProgress(): Found "
137 "database backup end time of %1 later than start time "
138 "of %2, therefore backup is not running.")
139 .arg(backupEndTimeStr, backupStartTimeStr));
140 return false;
141 }
142 if (backupElapsed > 10min)
143 {
144 LOG(VB_DATABASE, LOG_ERR,
145 QString("DBUtil::BackupInProgress(): "
146 "Database backup started at %1, but has not ended yet. "
147 "The backup started %2 seconds ago and should have "
148 "finished by now therefore it appears it is not running")
149 .arg(backupStartTimeStr)
150 .arg(backupElapsed.count()));
151 return false;
152 }
153
154 // start > end and started less than 10 minutes ago
155 LOG(VB_DATABASE, LOG_INFO, QString("DBUtil::BackupInProgress(): "
156 "Database backup started at %1, and is still running.")
157 .arg(backupStartTimeStr));
158 return true;
159}
160
187 [[maybe_unused]] bool disableRotation)
188{
189 filename = QString();
190
191#ifdef _WIN32
192 LOG(VB_GENERAL, LOG_CRIT, "Database backups disabled on Windows.");
193 return kDB_Backup_Disabled;
194#else
195
196 if (gCoreContext->GetBoolSetting("DisableAutomaticBackup", false))
197 {
198 LOG(VB_GENERAL, LOG_CRIT,
199 "Database backups disabled. Skipping backup.");
200 return kDB_Backup_Disabled;
201 }
202
203 if (IsNewDatabase())
204 {
205 LOG(VB_GENERAL, LOG_CRIT, "New database detected. Skipping backup.");
206 return kDB_Backup_Empty_DB;
207 }
208
209 QString backupScript = GetShareDir() + "mythconverg_backup.pl";
210 backupScript = gCoreContext->GetSetting("DatabaseBackupScript",
211 backupScript);
212
213 if (!QFile::exists(backupScript))
214 {
215 LOG(VB_GENERAL, LOG_CRIT, QString("Database backup script does "
216 "not exist: %1").arg(backupScript));
217 backupScript.clear();
218 }
219
220 bool result = false;
222
224 "BackupDBLastRunStart",
226
227 if (!backupScript.isEmpty())
228 {
229 result = DoBackup(backupScript, filename, disableRotation);
230 if (!result)
231 LOG(VB_GENERAL, LOG_CRIT, "Script-based database backup failed. "
232 "Retrying with internal backup.");
233 }
234
235 if (!result)
236 result = DoBackup(filename);
237
239 "BackupDBLastRunEnd",
241
242 if (query.isConnected())
243 {
244 QString dbTag("BackupDB");
245 query.prepare("DELETE FROM housekeeping WHERE tag = :TAG ;");
246 query.bindValue(":TAG", dbTag);
247 if (!query.exec())
248 MythDB::DBError("DBUtil::BackupDB", query);
249
250 query.prepare("INSERT INTO housekeeping(tag,lastrun) "
251 "values(:TAG ,now()) ;");
252 query.bindValue(":TAG", dbTag);
253 if (!query.exec())
254 MythDB::DBError("DBUtil::BackupDB", query);
255 }
256
257 if (result)
259
260 return kDB_Backup_Failed;
261#endif // _WIN32
262}
263
275bool DBUtil::CheckTables(const bool repair, const QString &options)
276{
278 if (!query.isConnected())
279 return false;
280
281 const QStringList all_tables = GetTables(QStringList("MyISAM"));
282
283 if (all_tables.empty())
284 return true;
285
286 QString sql = QString("CHECK TABLE %1 %2;")
287 .arg(all_tables.join(", "), options);
288
289 LOG(VB_GENERAL, LOG_CRIT, "Checking database tables.");
290 if (!query.exec(sql))
291 {
292 MythDB::DBError("DBUtil Checking Tables", query);
293 return false;
294 }
295
296 QStringList tables = CheckRepairStatus(query);
297 bool result = true;
298 if (!tables.empty())
299 {
300 LOG(VB_GENERAL, LOG_CRIT, QString("Found crashed database table(s): %1")
301 .arg(tables.join(", ")));
302 if (repair)
303 {
304 // If RepairTables() repairs the crashed tables, return true
305 result = RepairTables(tables);
306 }
307 else
308 {
309 result = false;
310 }
311 }
312
313 return result;
314}
315
333bool DBUtil::RepairTables(const QStringList &tables)
334{
336 if (!query.isConnected())
337 return false;
338
339 QString all_tables = tables.join(", ");
340 LOG(VB_GENERAL, LOG_CRIT, QString("Repairing database tables: %1")
341 .arg(all_tables));
342
343 QString sql = QString("REPAIR TABLE %1;").arg(all_tables);
344 if (!query.exec(sql))
345 {
346 MythDB::DBError("DBUtil Repairing Tables", query);
347 return false;
348 }
349
350 QStringList bad_tables = CheckRepairStatus(query);
351 bool result = true;
352 if (!bad_tables.empty())
353 {
354 LOG(VB_GENERAL, LOG_CRIT,
355 QString("Unable to repair crashed table(s): %1")
356 .arg(bad_tables.join(", ")));
357 result = false;
358 }
359 return result;
360}
361
381{
382 QStringList tables;
383 QSqlRecord record = query.record();
384 int table_index = record.indexOf("Table");
385 int type_index = record.indexOf("Msg_type");
386 int text_index = record.indexOf("Msg_text");
387 QString table;
388 QString type;
389 QString text;
390 QString previous_table;
391 bool ok = true;
392 while (query.next())
393 {
394 table = query.value(table_index).toString();
395 type = query.value(type_index).toString();
396 text = query.value(text_index).toString();
397 if (table != previous_table)
398 {
399 if (!ok)
400 {
401 tables.append(previous_table);
402 ok = true;
403 }
404 previous_table = table;
405 }
406 // If the final row shows status OK, the table is now good
407 if ("status" == type.toLower() && "ok" == text.toLower())
408 ok = true;
409 else if ("error" == type.toLower() ||
410 ("status" == type.toLower() && "ok" != text.toLower()))
411 ok = false;
412 }
413 // Check the last table in the list
414 if (!ok)
415 tables.append(table);
416 return tables;
417}
418
424QStringList DBUtil::GetTables(const QStringList &engines)
425{
426 QStringList result;
427
429 if (!query.isConnected())
430 return result;
431
432 QString sql = "SELECT CONCAT('`', TABLE_SCHEMA, "
433 " '`.`', TABLE_NAME, "
434 " '`') AS `TABLE_NAME` "
435 " FROM INFORMATION_SCHEMA.TABLES "
436 " WHERE TABLE_SCHEMA = DATABASE() "
437 " AND TABLE_TYPE = 'BASE TABLE'";
438 if (!engines.empty())
439 sql.append(QString(" AND ENGINE IN ('%1')")
440 .arg(engines.join("', '")));
441 if (!query.exec(sql))
442 {
443 MythDB::DBError("DBUtil Finding Tables", query);
444 return result;
445 }
446
447 while (query.next())
448 {
449 result.append(query.value(0).toString());
450 }
451
452 return result;
453}
454
467QString DBUtil::CreateBackupFilename(const QString& prefix, const QString& extension)
468{
470 return QString("%1-%2%3").arg(prefix, time, extension);
471}
472
483{
484 QString directory;
485 StorageGroup sgroup("DB Backups", gCoreContext->GetHostName());
486 QStringList dirList = sgroup.GetDirList();
487 if (!dirList.empty())
488 {
489 directory = sgroup.FindNextDirMostFree();
490
491 if (!QDir(directory).exists())
492 {
493 LOG(VB_FILE, LOG_INFO, "GetBackupDirectory() - ignoring " +
494 directory + ", using /tmp");
495 directory.clear();
496 }
497 }
498
499 if (directory.isNull())
500 {
501 // Rather than use kDefaultStorageDir, the default for
502 // FindNextDirMostFree() when no dirs are defined for the StorageGroup,
503 // use /tmp as it's possible that kDefaultStorageDir doesn't exist
504 // and (at least on *nix) less possible that /tmp doesn't exist
505 directory = "/tmp";
506 }
507
508 return directory;
509}
510
520 const QString &privateinfo, QString &filename)
521{
522 bool ok = true;
523 filename = createTempFile("/tmp/mythtv_db_backup_conf_XXXXXX");
524 const QByteArray tmpfile = filename.toLocal8Bit();
525
526 FILE *fp = fopen(tmpfile.constData(), "w");
527 if (!fp)
528 {
529 LOG(VB_GENERAL, LOG_ERR, LOC +
530 QString("Unable to create temporary "
531 "configuration file for creating DB backup: %1")
532 .arg(tmpfile.constData()));
533 filename = "";
534 ok = false;
535 }
536 else
537 {
538 if (chmod(tmpfile.constData(), S_IRUSR))
539 {
540 LOG(VB_GENERAL, LOG_ERR, LOC + QString("Error changing permissions '%1'")
541 .arg(tmpfile.constData()) + ENO);
542 }
543
544 QByteArray outarr = privateinfo.toLocal8Bit();
545 fprintf(fp, "%s", outarr.constData());
546
547 if (fclose(fp))
548 {
549 LOG(VB_GENERAL, LOG_ERR, LOC + QString("Error closing '%1'")
550 .arg(tmpfile.constData()) + ENO);
551 }
552 }
553
554 return ok;
555}
556
563bool DBUtil::DoBackup(const QString &backupScript, QString &filename,
564 bool disableRotation)
565{
566 DatabaseParams dbParams = GetMythDB()->GetDatabaseParams();
567 QString dbSchemaVer = gCoreContext->GetSetting("DBSchemaVer");
568 QString backupDirectory = GetBackupDirectory();
569 QString backupFilename = CreateBackupFilename(dbParams.m_dbName + "-" +
570 dbSchemaVer, ".sql");
571 QString scriptArgs = gCoreContext->GetSetting("BackupDBScriptArgs");
572 QString rotate = "";
573 if (disableRotation)
574 {
575 if (!(scriptArgs.contains("rotate", Qt::CaseInsensitive)))
576 rotate = "rotate=-1";
577 }
578
579
580 QString privateinfo =
581 QString("DBHostName=%1\nDBPort=%2\n"
582 "DBUserName=%3\nDBPassword=%4\n"
583 "DBName=%5\nDBSchemaVer=%6\n"
584 "DBBackupDirectory=%7\nDBBackupFilename=%8\n%9\n")
585 .arg(dbParams.m_dbHostName, QString::number(dbParams.m_dbPort),
586 dbParams.m_dbUserName, dbParams.m_dbPassword,
587 dbParams.m_dbName, dbSchemaVer,
588 backupDirectory, backupFilename,
589 rotate);
590 QString tempDatabaseConfFile;
591 bool hastemp = CreateTemporaryDBConf(privateinfo, tempDatabaseConfFile);
592 if (!hastemp)
593 LOG(VB_GENERAL, LOG_ERR, LOC + "Attempting backup, anyway.");
594
595 LOG(VB_GENERAL, LOG_ERR, QString("Backing up database with script: '%1'")
596 .arg(backupScript));
597
598 QString command = backupScript + " " + scriptArgs + " " +
599 tempDatabaseConfFile;
601
602 if (hastemp)
603 {
604 QByteArray tmpfile = tempDatabaseConfFile.toLocal8Bit();
605 unlink(tmpfile.constData());
606 }
607
608 if (status != GENERIC_EXIT_OK)
609 {
610 LOG(VB_GENERAL, LOG_ERR, LOC +
611 QString("Error backing up database: %1 (%2)")
612 .arg(command).arg(status));
613 filename = "__FAILED__";
614 return false;
615 }
616
617 LOG(VB_GENERAL, LOG_CRIT, "Database Backup complete.");
618
619 QDir dir(backupDirectory, backupFilename + "*");
620 uint numfiles = dir.count();
621 if (numfiles < 1)
622 {
623 // If no file begins with the suggested filename, don't show the backup
624 // filename in the GUI message -- the script probably used some other
625 // filename
626 filename = "";
627 LOG(VB_FILE, LOG_ERR, LOC +
628 QString("No files beginning with the suggested database backup "
629 "filename '%1' were found in '%2'.")
630 .arg(backupFilename, backupDirectory));
631 }
632 else
633 {
634 filename = dir.path() + "/" + dir[0];;
635 if (numfiles > 1)
636 {
637 LOG(VB_FILE, LOG_ERR, LOC +
638 QString("Multiple files beginning with the suggested database "
639 "backup filename '%1' were found in '%2'. "
640 "Assuming the first is the backup.")
641 .arg(backupFilename, backupDirectory));
642 }
643 }
644
645 if (!filename.isEmpty())
646 {
647 LOG(VB_GENERAL, LOG_CRIT, QString("Backed up database to file: '%1'")
648 .arg(filename));
649 }
650
651 return true;
652}
653
661{
662 DatabaseParams dbParams = GetMythDB()->GetDatabaseParams();
663 QString dbSchemaVer = gCoreContext->GetSetting("DBSchemaVer");
664 QString backupDirectory = GetBackupDirectory();
665
666 QString command;
667 QString compressCommand("");
668 QString extension = ".sql";
669 if (QFile::exists("/bin/gzip"))
670 compressCommand = "/bin/gzip";
671 else if (QFile::exists("/usr/bin/gzip"))
672 compressCommand = "/usr/bin/gzip";
673 else
674 LOG(VB_GENERAL, LOG_CRIT, "Neither /bin/gzip nor /usr/bin/gzip exist. "
675 "The database backup will be uncompressed.");
676
677 QString backupFilename = CreateBackupFilename(
678 dbParams.m_dbName + "-" + dbSchemaVer, extension);
679 QString backupPathname = backupDirectory + "/" + backupFilename;
680
681 QString privateinfo = QString(
682 "[client]\npassword=%1\n[mysqldump]\npassword=%2\n")
683 .arg(dbParams.m_dbPassword, dbParams.m_dbPassword);
684 QString tempExtraConfFile;
685 if (!CreateTemporaryDBConf(privateinfo, tempExtraConfFile))
686 return false;
687
688 QString portArg = "";
689 if (dbParams.m_dbPort > 0)
690 portArg = QString(" --port='%1'").arg(dbParams.m_dbPort);
691 command = QString("mysqldump --defaults-extra-file='%1' --host='%2'%3"
692 " --user='%4' --add-drop-table --add-locks"
693 " --allow-keywords --complete-insert"
694 " --extended-insert --lock-tables --no-create-db --quick"
695 " '%5' > '%6' 2>/dev/null")
696 .arg(tempExtraConfFile, dbParams.m_dbHostName,
697 portArg, dbParams.m_dbUserName,
698 dbParams.m_dbName, backupPathname);
699
700 LOG(VB_FILE, LOG_INFO, QString("Backing up database with command: '%1'")
701 .arg(command));
702 LOG(VB_GENERAL, LOG_CRIT, QString("Backing up database to file: '%1'")
703 .arg(backupPathname));
704
706
707 QByteArray tmpfile = tempExtraConfFile.toLocal8Bit();
708 unlink(tmpfile.constData());
709
710 if (status != GENERIC_EXIT_OK)
711 {
712 LOG(VB_GENERAL, LOG_ERR, LOC +
713 QString("Error backing up database: '%1' (%2)")
714 .arg(command).arg(status));
715 filename = "__FAILED__";
716 return false;
717 }
718
719 if (compressCommand != "")
720 {
721 LOG(VB_GENERAL, LOG_CRIT, "Compressing database backup file.");
722 compressCommand += " " + backupPathname;
723 status = myth_system(compressCommand, kMSDontBlockInputDevs);
724
725 if (status != GENERIC_EXIT_OK)
726 {
727 LOG(VB_GENERAL, LOG_CRIT,
728 "Compression failed, backup file will remain uncompressed.");
729 }
730 else
731 {
732 backupPathname += ".gz";
733
734 LOG(VB_GENERAL, LOG_CRIT, QString("Database Backup filename: '%1'")
735 .arg(backupPathname));
736 }
737 }
738
739 LOG(VB_GENERAL, LOG_CRIT, "Database Backup complete.");
740
741 filename = backupPathname;
742 return true;
743}
744
750{
751 // Allow users to override the string provided by the database server in
752 // case the value was changed to an unrecognizable string by whomever
753 // compiled the MySQL server
754 QString dbmsVersion = gCoreContext->GetSetting("DBMSVersionOverride");
755
756 if (dbmsVersion.isEmpty())
757 {
759 query.prepare("SELECT VERSION();");
760 if (!query.exec() || !query.next())
761 {
762 LOG(VB_GENERAL, LOG_ERR, LOC +
763 "Unable to determine MySQL version.");
764 MythDB::DBError("DBUtil Querying DBMS version", query);
765 dbmsVersion.clear();
766 }
767 else
768 {
769 dbmsVersion = query.value(0).toString();
770 }
771 }
772 m_versionString = dbmsVersion;
773
774 return !m_versionString.isEmpty();
775}
776
781{
782 if (m_versionString.isEmpty())
783 if (!QueryDBMSVersion())
784 return false;
785
786 static const QRegularExpression parseVersion
787 { R"(^(\d+)(?:\.(\d+)(?:\.(\d+))?)?)" };
788 auto match = parseVersion.match(m_versionString);
789 if (!match.hasMatch())
790 return false;
791
792 // If any of these wasn't matched, the captured string will be
793 // empty and toInt will parse it as a zero.
794 m_versionMajor = match.capturedView(1).toInt(nullptr);
795 m_versionMinor = match.capturedView(2).toInt(nullptr);
796 m_versionPoint = match.capturedView(3).toInt(nullptr);
797
798 return m_versionMajor > -1;
799}
800
805{
806 int count = 0;
807
809 if (!query.isConnected())
810 {
811 LOG(VB_GENERAL, LOG_DEBUG, "Not connected to DB");
812 return count;
813 }
814
815 if (!query.exec("SHOW PROCESSLIST;"))
816 {
817 MythDB::DBError("DBUtil CountClients", query);
818 return count;
819 }
820
821 QSqlRecord record = query.record();
822 int db_index = record.indexOf("db");
823 QString dbName = GetMythDB()->GetDatabaseName();
824 QString inUseDB;
825
826 while (query.next())
827 {
828 inUseDB = query.value(db_index).toString();
829 if (inUseDB == dbName)
830 ++count;
831 }
832
833 // On average, each myth program has 4 database connections,
834 // but we round up just in case a new program is loading:
835 count = (count + 3)/4;
836
837 LOG(VB_GENERAL, LOG_DEBUG,
838 QString("DBUtil::CountClients() found %1").arg(count));
839
840 return count;
841}
842
846bool DBUtil::TryLockSchema(MSqlQuery &query, uint timeout_secs)
847{
848 query.prepare("SELECT GET_LOCK('schemaLock', :TIMEOUT)");
849 query.bindValue(":TIMEOUT", timeout_secs);
850 return query.exec() && query.first() && query.value(0).toBool();
851}
852
854{
855 query.prepare("SELECT RELEASE_LOCK('schemaLock')");
856 if (!query.exec())
857 {
858 MythDB::DBError("DBUtil UnlockSchema", query);
859 }
860}
861
866{
868 query.prepare("SELECT CONVERT_TZ(NOW(), 'SYSTEM', 'Etc/UTC')");
869 if (!query.exec() || !query.next())
870 {
871 LOG(VB_GENERAL, LOG_ERR, "MySQL time zone support check failed");
872 return false;
873 }
874
875 return !query.value(0).isNull();
876}
877
889bool DBUtil::CheckTableColumnExists(const QString &tableName, const QString &columnName)
890{
892 if (!query.isConnected())
893 return false;
894
895 QString sql = QString("SELECT COUNT(*) FROM information_schema.columns "
896 "WHERE table_schema = DATABASE() AND "
897 "table_name = '%1' AND column_name = '%2';")
898 .arg(tableName, columnName);
899 LOG(VB_GENERAL, LOG_DEBUG,
900 QString("DBUtil::CheckTableColumnExists() SQL: %1").arg(sql));
901
902 if (!query.exec(sql))
903 {
904 MythDB::DBError("DBUtil Check Table Column Exists", query);
905 return false;
906 }
907
908 bool result = false;
909 if (query.next())
910 {
911 result = (query.value(0).toInt() > 0);
912 }
913 else
914 {
915 LOG(VB_GENERAL, LOG_ERR,
916 QString("DBUtil::CheckTableColumnExists() - Empty result set"));
917 }
918
919 LOG(VB_GENERAL, LOG_DEBUG,
920 QString("DBUtil::CheckTableColumnExists('%1', '%2') result: %3").arg(tableName,
921 columnName, QVariant(result).toString()));
922
923 return result;
924}
925
926/* vim: set expandtab tabstop=4 shiftwidth=4: */
static MythDBBackupStatus BackupDB(QString &filename, bool disableRotation=false)
Requests a backup of the database.
Definition: dbutil.cpp:186
static bool CheckTables(bool repair=false, const QString &options="QUICK")
Checks database tables.
Definition: dbutil.cpp:275
bool ParseDBMSVersion(void)
Parses m_versionString to find the major, minor, and point version.
Definition: dbutil.cpp:780
bool QueryDBMSVersion(void)
Reads and returns the QString version name from the DBMS or returns QString() in the event of an erro...
Definition: dbutil.cpp:749
static bool RepairTables(const QStringList &tables)
Repairs database tables.
Definition: dbutil.cpp:333
int m_versionMinor
Definition: dbutil.h:82
int CompareDBMSVersion(int major, int minor=0, int point=0)
Compares the version of the active DBMS with the provided version.
Definition: dbutil.cpp:53
static QString CreateBackupFilename(const QString &prefix="mythconverg", const QString &extension=".sql")
Creates a filename to use for the filename.
Definition: dbutil.cpp:467
static void UnlockSchema(MSqlQuery &query)
Definition: dbutil.cpp:853
QString m_versionString
Definition: dbutil.h:79
static bool IsBackupInProgress(void)
Test to see if a DB backup is in progress.
Definition: dbutil.cpp:88
static int CountClients(void)
Estimate the number of MythTV programs using the database.
Definition: dbutil.cpp:804
static QString GetBackupDirectory()
Determines the appropriate path for the database backup.
Definition: dbutil.cpp:482
static bool TryLockSchema(MSqlQuery &query, uint timeout_secs)
Try to get a lock on the table schemalock.
Definition: dbutil.cpp:846
static const int kUnknownVersionNumber
Definition: dbutil.h:58
static bool CheckTableColumnExists(const QString &tableName, const QString &columnName)
Checks for the presence of a column in a table in the current database.
Definition: dbutil.cpp:889
static bool CreateTemporaryDBConf(const QString &privateinfo, QString &filename)
Creates temporary file containing sensitive DB info.
Definition: dbutil.cpp:519
QString GetDBMSVersion(void)
Returns the QString version name of the DBMS or QString() in the event of an error.
Definition: dbutil.cpp:34
int m_versionPoint
Definition: dbutil.h:83
static bool CheckTimeZoneSupport(void)
Check if MySQL has working timz zone support.
Definition: dbutil.cpp:865
static QStringList GetTables(const QStringList &engines=QStringList())
Retrieves a list of tables from the database.
Definition: dbutil.cpp:424
static QStringList CheckRepairStatus(MSqlQuery &query)
Parse the results of a CHECK TABLE or REPAIR TABLE run.
Definition: dbutil.cpp:380
static bool IsNewDatabase(void)
Returns true for a new (empty) database.
Definition: dbutil.cpp:74
int m_versionMajor
Definition: dbutil.h:81
static bool DoBackup(const QString &backupScript, QString &filename, bool disableRotation=false)
Creates a backup of the database by executing the backupScript.
Definition: dbutil.cpp:563
Structure containing the basic Database parameters.
Definition: mythdbparams.h:11
QString m_dbName
database name
Definition: mythdbparams.h:26
QString m_dbPassword
DB password.
Definition: mythdbparams.h:25
QString m_dbUserName
DB user name.
Definition: mythdbparams.h:24
int m_dbPort
database port
Definition: mythdbparams.h:23
QString m_dbHostName
database server
Definition: mythdbparams.h:21
QSqlQuery wrapper that fetches a DB connection from the connection pool.
Definition: mythdbcon.h:128
bool prepare(const QString &query)
QSqlQuery::prepare() is not thread safe in Qt <= 3.3.2.
Definition: mythdbcon.cpp:837
QSqlRecord record(void) const
Definition: mythdbcon.h:216
bool first(void)
Wrap QSqlQuery::first() so we can display the query results.
Definition: mythdbcon.cpp:822
QVariant value(int i) const
Definition: mythdbcon.h:204
bool isConnected(void) const
Only updated once during object creation.
Definition: mythdbcon.h:137
bool exec(void)
Wrap QSqlQuery::exec() so we can display SQL.
Definition: mythdbcon.cpp:618
void bindValue(const QString &placeholder, const QVariant &val)
Add a single binding.
Definition: mythdbcon.cpp:888
bool next(void)
Wrap QSqlQuery::next() so we can display the query results.
Definition: mythdbcon.cpp:812
static MSqlQueryInfo InitCon(ConnectionReuse _reuse=kNormalConnection)
Only use this in combination with MSqlQuery constructor.
Definition: mythdbcon.cpp:550
QString GetHostName(void)
QString GetSetting(const QString &key, const QString &defaultval="")
bool SaveSettingOnHost(const QString &key, const QString &newValue, const QString &host)
bool GetBoolSetting(const QString &key, bool defaultval=false)
static void DBError(const QString &where, const MSqlQuery &query)
Definition: mythdb.cpp:226
QStringList GetDirList(void) const
Definition: storagegroup.h:23
QString FindNextDirMostFree(void)
#define minor(X)
Definition: compat.h:74
#define LOC
Definition: dbutil.cpp:26
MythDBBackupStatus
Definition: dbutil.h:10
@ kDB_Backup_Disabled
Definition: dbutil.h:15
@ kDB_Backup_Failed
Definition: dbutil.h:12
@ kDB_Backup_Empty_DB
Definition: dbutil.h:14
@ kDB_Backup_Completed
Definition: dbutil.h:13
@ GENERIC_EXIT_OK
Exited with no error.
Definition: exitcodes.h:13
unsigned int uint
Definition: freesurround.h:24
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
MythDB * GetMythDB(void)
Definition: mythdb.cpp:51
QString GetShareDir(void)
Definition: mythdirs.cpp:261
#define ENO
This can be appended to the LOG args with "+".
Definition: mythlogging.h:74
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
QString createTempFile(QString name_template, bool dir)
@ kMSDontBlockInputDevs
avoid blocking LIRC & Joystick Menu
Definition: mythsystem.h:36
@ kMSAnonLog
anonymize the logs
Definition: mythsystem.h:44
uint myth_system(const QString &command, uint flags, std::chrono::seconds timeout)
std::chrono::seconds secsInPast(const QDateTime &past)
Definition: mythdate.cpp:212
QString toString(const QDateTime &raw_dt, uint format)
Returns formatted string representing the time.
Definition: mythdate.cpp:93
@ kFilename
Default UTC, "yyyyMMddhhmmss".
Definition: mythdate.h:18
@ kDatabase
Default UTC, database format.
Definition: mythdate.h:27
QDateTime fromString(const QString &dtstr)
Converts kFilename && kISODate formats to QDateTime.
Definition: mythdate.cpp:39
QDateTime current(bool stripped)
Returns current Date and Time in UTC.
Definition: mythdate.cpp:15
string version
Definition: giantbomb.py:185
int FILE
Definition: mythburn.py:138
bool exists(str path)
Definition: xbmcvfs.py:51