File indexing completed on 2025-12-17 09:19:36
0001 #include "ODBCInterface.h"
0002
0003 #include <odbc++/connection.h>
0004 #include <odbc++/drivermanager.h>
0005 #include <odbc++/resultset.h>
0006 #include <odbc++/statement.h> // for Statement
0007 #include <odbc++/types.h>
0008
0009 #include <cassert>
0010 #include <chrono>
0011 #include <cmath>
0012 #include <iostream>
0013 #include <random> // For retrying connections
0014 #include <string>
0015 #include <thread>
0016
0017 ODBCInterface *ODBCInterface::__instance{nullptr};
0018
0019 ODBCInterface *ODBCInterface::instance()
0020 {
0021 if (!__instance)
0022 {
0023 __instance = new ODBCInterface();
0024 }
0025 return __instance;
0026 }
0027
0028 ODBCInterface::~ODBCInterface()
0029 {
0030 ODBCInterface::Disconnect();
0031 __instance = nullptr;
0032 return;
0033 }
0034
0035 odbc::Connection *ODBCInterface::getDBConnection(const std::string &dbname)
0036 {
0037 auto coniter = m_OdbcConnectionMap.find(dbname);
0038 if (coniter != m_OdbcConnectionMap.end())
0039 {
0040 return coniter->second;
0041 }
0042 m_NumConnection[dbname]++;
0043 std::random_device ran_dev;
0044 std::seed_seq seeds{ran_dev(), ran_dev(), ran_dev()};
0045 std::mt19937_64 mersenne_twister(seeds);
0046 std::uniform_int_distribution<> uniform(m_MIN_SLEEP_DUR, m_MAX_SLEEP_DUR);
0047 odbc::Connection *dbcon{nullptr};
0048 for (int num_tries = 0; num_tries < m_MAX_NUM_RETRIES; ++num_tries)
0049 {
0050 try
0051 {
0052 dbcon = odbc::DriverManager::getConnection(dbname, "", "");
0053 }
0054 catch (odbc::SQLException &e)
0055 {
0056 std::cout << ": SQL Exception: " << e.getMessage() << std::endl;
0057 }
0058
0059 if (dbcon)
0060 {
0061 break;
0062 }
0063 ++m_ConnectionTries;
0064 int sleep_time_ms = uniform(mersenne_twister);
0065 std::this_thread::sleep_for(std::chrono::milliseconds(sleep_time_ms));
0066 m_SleepMS += sleep_time_ms;
0067
0068 if (0 < Verbosity())
0069 {
0070 std::cout << "Connection unsuccessful, Sleeping for addtional "
0071 << sleep_time_ms << " ms" << std::endl;
0072 }
0073 }
0074 if (1 < Verbosity())
0075 {
0076 std::cout << ": Connection successful (" << m_ConnectionTries
0077 << " attempts, " << m_SleepMS << " ms)" << std::endl;
0078 }
0079 if (!dbcon)
0080 {
0081 std::cout << ": DB Connection failed after " << m_MAX_NUM_RETRIES
0082 << " retries, abandoning query" << std::endl;
0083 return nullptr;
0084 }
0085 m_CurrentConnections++;
0086 m_OdbcConnectionMap.insert(std::make_pair(dbname, dbcon));
0087 return dbcon;
0088 }
0089
0090 odbc::Statement *ODBCInterface::getStatement(const std::string &dbname)
0091 {
0092 m_NumStatementUse[dbname]++;
0093 auto statiter = m_OdbcStatementMap.find(dbname);
0094 if (statiter != m_OdbcStatementMap.end())
0095 {
0096 return statiter->second;
0097 }
0098 odbc::Connection *dbcon = getDBConnection(dbname);
0099 odbc::Statement *statement = dbcon->createStatement();
0100 m_OdbcStatementMap.insert(std::make_pair(dbname, statement));
0101 return statement;
0102 }
0103
0104
0105 void ODBCInterface::Print(const std::string & ) const
0106 {
0107 if (m_NumConnection.empty())
0108 {
0109 std::cout << "No ODBC connections cached" << std::endl;
0110 }
0111 else
0112 {
0113 std::cout << "Odbc Connections Opened: " << std::endl;
0114 for (auto const &iter: m_NumConnection)
0115 {
0116 std::cout << "db: " << iter.first << ", opened: " << iter.second << std::endl;
0117 }
0118 }
0119 if (m_NumStatementUse.empty())
0120 {
0121 std::cout << "No odbc::Statements cached" << std::endl;
0122 }
0123 else
0124 {
0125 std::cout << "Odbc Statement use: " << std::endl;
0126 for (auto const &iter: m_NumStatementUse)
0127 {
0128 std::cout << "db: " << iter.first << ", Statement use: " << iter.second << std::endl;
0129 }
0130 }
0131 return;
0132 }
0133
0134 void ODBCInterface::Disconnect()
0135 {
0136 if (!m_OdbcConnectionMap.empty())
0137 {
0138 for (const auto& iter : m_OdbcConnectionMap)
0139 {
0140 delete iter.second;
0141 }
0142 m_OdbcConnectionMap.clear();
0143 }
0144 if (!m_OdbcStatementMap.empty())
0145 {
0146 m_OdbcStatementMap.clear();
0147 }
0148 m_CurrentConnections = 0;
0149 }