EasyQtSql_SqlFactory.h 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. #ifndef EASYQTSQL_SQLFACTORY_H
  2. #define EASYQTSQL_SQLFACTORY_H
  3. /*
  4. * The MIT License (MIT)
  5. * Copyright 2018 Alexey Kramin
  6. *
  7. * Permission is hereby granted, free of charge, to any person obtaining
  8. * a copy of this software and associated documentation files (the
  9. * "Software"), to deal in the Software without restriction, including
  10. * without limitation the rights to use, copy, modify, merge, publish,
  11. * distribute, sublicense, and/or sell copies of the Software, and to
  12. * permit persons to whom the Software is furnished to do so, subject to
  13. * the following conditions:
  14. *
  15. * The above copyright notice and this permission notice shall be
  16. * included in all copies or substantial portions of the Software.
  17. *
  18. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  19. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  20. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  21. * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  22. * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  23. * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  24. * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  25. *
  26. */
  27. #ifndef EASY_QT_SQL_MAIN
  28. # include <QtSql>
  29. #endif
  30. class SqlFactory
  31. {
  32. public:
  33. static SqlFactory *getInstance()
  34. {
  35. static SqlFactory instance;
  36. return &instance;
  37. }
  38. static SqlFactory *getInstance2()
  39. {
  40. static SqlFactory instance2;
  41. return &instance2;
  42. }
  43. class ThreadDBPool;
  44. struct DBSetting
  45. {
  46. friend class ThreadDBPool;
  47. DBSetting() { }
  48. DBSetting(const QString &type, const QString &host, int port, const QString &username, const QString &password,
  49. const QString &dbname)
  50. : type(type), port(port), host(host), username(username), password(password), dbName(dbname)
  51. {
  52. }
  53. DBSetting(const QString &type, const QString &connectionString) : type(type), dbName(connectionString) { }
  54. static DBSetting sqliteInmemory() { return DBSetting("QSQLITE", ":memory:"); }
  55. QString getType() const { return type.isEmpty() ? "QODBC" : type; }
  56. private:
  57. QString type;
  58. QVariant port;
  59. QString host;
  60. QString username;
  61. QString password;
  62. QString dbName;
  63. };
  64. class ThreadDBPool
  65. {
  66. public:
  67. ~ThreadDBPool()
  68. {
  69. for (const QString &uniqueConnName : m_connNameMap.values()) {
  70. {
  71. QSqlDatabase db = QSqlDatabase::database(uniqueConnName);
  72. if (db.isOpen()) {
  73. db.close();
  74. }
  75. }
  76. QSqlDatabase::removeDatabase(uniqueConnName);
  77. }
  78. }
  79. void addConnection(const DBSetting &settings, const QString &connectionName)
  80. {
  81. const QString uniqueConnectionName = connectionName + QUuid::createUuid().toString();
  82. m_connNameMap.insert(connectionName, uniqueConnectionName);
  83. QSqlDatabase db = QSqlDatabase::addDatabase(settings.getType(), uniqueConnectionName);
  84. db.setDatabaseName(settings.dbName);
  85. db.setHostName(settings.host);
  86. db.setUserName(settings.username);
  87. db.setPassword(settings.password);
  88. if (settings.port.isValid()) {
  89. db.setPort(settings.port.toInt());
  90. }
  91. }
  92. bool connectionExists(const QString &connectionName) const { return m_connNameMap.contains(connectionName); }
  93. QSqlDatabase getDatabase(const QString &connectionName) const
  94. {
  95. const QString &uniqueConnectionName = m_connNameMap.value(connectionName);
  96. QSqlDatabase db = QSqlDatabase::database(uniqueConnectionName);
  97. if (!db.isOpen()) {
  98. if (!db.open()) {
  99. qCritical() << db.lastError().text();
  100. }
  101. }
  102. return db;
  103. }
  104. private:
  105. QMap<QString, QString> m_connNameMap;
  106. };
  107. SqlFactory *config(const DBSetting &settings, const QString &connectionName = QSqlDatabase::defaultConnection)
  108. {
  109. QMutexLocker locker(&mutex);
  110. m_settings.insert(connectionName, settings);
  111. return this;
  112. }
  113. QSqlDatabase getDatabase(const QString &connectionName = QSqlDatabase::defaultConnection)
  114. {
  115. QMutexLocker locker(&mutex);
  116. if (m_settings.contains(connectionName)) {
  117. ThreadDBPool *threadDbPool = nullptr;
  118. if (!m_dbPool.hasLocalData()) {
  119. threadDbPool = new ThreadDBPool(); // new pool for current thread
  120. m_dbPool.setLocalData(threadDbPool);
  121. } else {
  122. threadDbPool = m_dbPool.localData();
  123. }
  124. if (threadDbPool) {
  125. if (!threadDbPool->connectionExists(connectionName)) // if no connection created for current thread
  126. {
  127. const DBSetting &settings = m_settings[connectionName];
  128. threadDbPool->addConnection(
  129. settings,
  130. connectionName); // create new connection with specified settings for current thread
  131. }
  132. return threadDbPool->getDatabase(connectionName);
  133. }
  134. }
  135. return QSqlDatabase();
  136. }
  137. private:
  138. QMutex mutex;
  139. QMap<QString, DBSetting> m_settings;
  140. QThreadStorage<ThreadDBPool *> m_dbPool;
  141. QString m_defaultConnName;
  142. private:
  143. SqlFactory() { }
  144. };
  145. #endif // EASYQTSQL_SQLFACTORY_H