2025-05-30 16:35:54 +02:00 | | | //+------------------------------------------------------------------+
|
| | | //| Warrior_EA |
|
| | | //| AnimateDread |
|
| | | //| |
|
| | | //+------------------------------------------------------------------+
|
| | | #include "DatabaseConnectionManager.mqh"
|
| | | #include "DatabaseOperationsManager.mqh"
|
| | | #include "DatabaseFileSystemManager.mqh"
|
| | | #include "DatabaseVersionManager.mqh"
|
| | | class CDatabaseManager
|
| | | {
|
| | | private:
|
| | | string m_dbPath;
|
| | | int m_databaseHandle;
|
| | | bool m_isDatabaseOpen; // Tracks if the database is currently open
|
| | |
|
| | | CDatabaseConnectionManager m_dbConnectionManager;
|
| | | CDatabaseVersionManager m_dbVersionManager;
|
| | | CDatabaseFileSystemManager m_dbFileSystemManager;
|
| | | CDatabaseOperationsManager m_dbOperationsManager;
|
| | |
|
| | | public:
|
| | | CDatabaseManager()
|
| | | {
|
| | | m_isDatabaseOpen = false;
|
| | | }
|
| | |
|
| | | ~CDatabaseManager()
|
| | | {
|
| | | CloseDatabase();
|
| | | }
|
| | |
|
| | | bool Init(const string& dbVersion, string& dirStructureArray[], const string& dbName)
|
| | | {
|
| | | string currentPath;
|
| | | // Build the database folder path
|
| | | for(int i = 0; i < ArraySize(dirStructureArray); ++i)
|
| | | {
|
| | | currentPath += (i == 0) ? dirStructureArray[i] : "\\" + dirStructureArray[i];
|
| | | }
|
| | | string dbFolderPath = currentPath;
|
| | | string versionFilePath = dbFolderPath + "\\" + "DatabaseVersion";
|
| | | m_dbPath = dbFolderPath + "\\" + dbName;
|
| | | string storedDbVersion = m_dbVersionManager.ReadStoredDbVersion(versionFilePath);
|
| | | // Handling when the stored database version is "NA"
|
| | | if(storedDbVersion == "NA")
|
| | | {
|
| | | if(!m_dbFileSystemManager.CreateDirectory(dbFolderPath))
|
| | | {
|
| | | return false;
|
| | | }
|
| | | m_dbFileSystemManager.CleanDirectory(dbFolderPath);
|
| | | m_dbVersionManager.UpdateStoredDbVersion(versionFilePath, dbVersion);
|
| | | }
|
| | | else
|
| | | if(storedDbVersion == "ERROR")
|
| | | {
|
2026-08-24 02:26:56 -04:00 | | | // ReadStoredDbVersion() already retried the FileOpen 5x internally (1s sleep each) -
|
| | | // a second wrapper loop here would just re-run that whole sequence again for no
|
| | | // meaningfully better odds. Treat one exhausted "ERROR" as a hard Init() failure.
|
| | | return false;
|
2025-05-30 16:35:54 +02:00 | | | }
|
| | | // If current version doesn't match the stored version (and it's not "NA" or "ERROR")
|
| | | if(storedDbVersion != dbVersion && storedDbVersion != "")
|
| | | {
|
| | | m_dbFileSystemManager.CleanDirectory(dbFolderPath);
|
| | | m_dbVersionManager.UpdateStoredDbVersion(versionFilePath, dbVersion);
|
| | | }
|
| | | // Attempt to initialize the database connection
|
| | | if(!m_dbConnectionManager.Init(m_dbPath))
|
| | | {
|
| | | return false;
|
| | | }
|
| | | return true;
|
| | | }
|
| | |
|
| | | bool Deinit()
|
| | | {
|
| | | m_dbConnectionManager.TransactionCommit();
|
| | | m_dbConnectionManager.CloseDatabase();
|
| | | return(true);
|
| | | }
|
| | |
|
| | | bool OpenDatabase()
|
| | | {
|
| | | // Check if the database is already open
|
| | | if(m_isDatabaseOpen)
|
| | | {
|
| | | // Database is already open, no need to open it again
|
| | | PrintVerbose("Database already open.");
|
| | | return true;
|
| | | }
|
| | | if(m_dbConnectionManager.OpenDatabase())
|
| | | {
|
| | | m_databaseHandle = m_dbConnectionManager.GetDatabaseHandle();
|
| | | m_dbOperationsManager.SetDatabaseHandle(m_databaseHandle);
|
| | | m_isDatabaseOpen = true; // Update the state to reflect that the database is now open
|
| | | return true;
|
| | | }
|
| | | else
|
| | | return false;
|
| | | }
|
| | |
|
| | | bool CloseDatabase()
|
| | | {
|
| | | if(m_dbConnectionManager.CloseDatabase())
|
| | | {
|
| | | m_databaseHandle = 0; // Reset database handle
|
| | | m_dbOperationsManager.SetDatabaseHandle(m_databaseHandle);
|
| | | m_isDatabaseOpen = false; // Update the state to reflect that the database is now closed
|
| | | return true;
|
| | | }
|
| | | else
|
| | | return false;
|
| | | }
|
| | |
|
| | | bool BeginTransaction()
|
| | | {
|
| | | if(!m_isDatabaseOpen)
|
| | | {
|
| | | if(!OpenDatabase())
|
| | | return false;
|
| | | }
|
| | | return m_dbConnectionManager.TransactionBegin();
|
| | | }
|
| | |
|
| | | bool CommitTransaction()
|
| | | {
|
| | | return m_dbConnectionManager.TransactionCommit();
|
| | | }
|
| | |
|
2026-07-26 12:12:14 -04:00 | | | bool RollbackTransaction()
|
| | | {
|
| | | return m_dbConnectionManager.TransactionRollback();
|
| | | }
|
| | |
|
2025-05-30 16:35:54 +02:00 | | | bool CreateTable(string tableName, string tableSchema)
|
| | | {
|
| | | return m_dbOperationsManager.CreateTable(tableName, tableSchema);
|
| | | }
|
| | |
|
| | | bool DeleteTable(string tableName)
|
| | | {
|
| | | return m_dbOperationsManager.DeleteTable(tableName);
|
| | | }
|
| | |
|
| | | bool InsertTradeRecord(string tableName, const string &columns[], const string &values[])
|
| | | {
|
| | | return m_dbOperationsManager.InsertTradeRecord(tableName, columns, values);
|
| | | }
|
| | |
|
| | | template <typename T>
|
| | | bool FetchTradeRecords(string tableName, T &tradeRecordStructure, T &tradeRecords[])
|
| | | {
|
| | | return m_dbOperationsManager.FetchTradeRecords(tableName, tradeRecordStructure, tradeRecords);
|
| | | }
|
| | |
|
2026-08-12 19:02:11 -04:00 | | | bool FetchRecordCount(string tableName, int &count)
|
| | | {
|
| | | return m_dbOperationsManager.FetchRecordCount(tableName, count);
|
| | | }
|
| | |
|
2026-08-12 18:53:04 -04:00 | | | bool FetchOpenTradeEntry(string tableName, string pattern, string direction, double &entryPrice, bool &found)
|
| | | {
|
| | | return m_dbOperationsManager.FetchOpenTradeEntry(tableName, pattern, direction, entryPrice, found);
|
| | | }
|
| | |
|
2026-08-12 23:56:26 -04:00 | | | bool FetchNewestTimeKey(string tableName, long &key, bool &found, const bool quiet = false)
|
2026-08-12 18:53:04 -04:00 | | | {
|
2026-08-12 23:56:26 -04:00 | | | return m_dbOperationsManager.FetchNewestTimeKey(tableName, key, found, quiet);
|
2026-08-12 18:53:04 -04:00 | | | }
|
| | |
|
| | | bool FetchWinLossCounts(string tableName, long beforeKey, int &wins, int &losses)
|
| | | {
|
| | | return m_dbOperationsManager.FetchWinLossCounts(tableName, beforeKey, wins, losses);
|
| | | }
|
| | |
|
2026-07-13 03:23:39 -04:00 | | | bool UpdateTradeRecord(string tableName, const string &columns[], const string &values[], string pattern, string direction)
|
2025-05-30 16:35:54 +02:00 | | | {
|
2026-07-13 03:23:39 -04:00 | | | return m_dbOperationsManager.UpdateTradeRecord(tableName, columns, values, pattern, direction);
|
2025-05-30 16:35:54 +02:00 | | | }
|
| | |
|
| | | bool DeleteOldestEntry(string tableName)
|
| | | {
|
| | | return m_dbOperationsManager.DeleteOldestEntry(tableName);
|
| | | }
|
2026-07-22 22:51:04 -04:00 | | |
|
| | | //--- Panel "Reset" button equivalent for the pattern-confidence DB (was previously only reachable
|
| | | //--- headless via the trainingMode input at Init() time). Closes the connection if open, deletes the
|
| | | //--- DB file, and reopens - the next UpdateSignalsWeights() pass recreates tables lazily (CreateTable
|
| | | //--- is IF-NOT-EXISTS), so no explicit re-init is needed here.
|
| | | bool ResetDatabase()
|
| | | {
|
| | | bool wasOpen = m_isDatabaseOpen;
|
| | | if(wasOpen)
|
| | | CloseDatabase();
|
| | | ResetLastError();
|
| | | if(!m_dbFileSystemManager.DeleteFile(m_dbPath) && GetLastError() != 5002) // 5002: file does not exist
|
| | | Print(__FUNCTION__ + ": failed to delete " + m_dbPath + ", error " + IntegerToString(GetLastError()));
|
| | | return wasOpen ? OpenDatabase() : true;
|
| | | }
|
2025-05-30 16:35:54 +02:00 | | | };
|
| | | //+------------------------------------------------------------------+
|