25 #define DEBUG_RECONNECT 0
40 if (dbHostName.isEmpty() || dbUserName.isEmpty())
75 m_db = QSqlDatabase::addDatabase(
"QMYSQL",
m_name);
76 LOG(VB_DATABASE, LOG_INFO,
"Database connection created: " +
m_name);
80 LOG(VB_GENERAL, LOG_ERR,
"Unable to init db connection.");
91 m_db = QSqlDatabase();
94 QSqlDatabase::removeDatabase(
m_name);
95 LOG(VB_DATABASE, LOG_INFO,
"Database connection deleted: " +
m_name);
113 LOG(VB_GENERAL, LOG_ERR,
114 "MSqlDatabase::OpenDatabase(), db object is not valid!");
118 bool connected =
true;
144 m_db.setHostName(
"localhost");
146 connected =
m_db.open();
154 LOG(VB_GENERAL, LOG_INFO,
155 QString(
"Using WOL to wakeup database server (Try %1 of "
161 LOG(VB_GENERAL, LOG_ERR,
162 QString(
"Failed to run WOL command '%1'")
167 connected =
m_db.open();
172 LOG(VB_GENERAL, LOG_ERR,
173 "WOL failed, unable to connect to database!");
178 LOG(VB_DATABASE, LOG_INFO,
179 QString(
"Connected to database '%1' at host: %2")
180 .arg(
m_db.databaseName()).arg(
m_db.hostName()));
192 bool have_schema =
false;
193 QString sql =
"SELECT COUNT( "
194 " INFORMATION_SCHEMA.TABLES.TABLE_NAME "
196 " FROM INFORMATION_SCHEMA.TABLES "
197 " WHERE INFORMATION_SCHEMA.TABLES.TABLE_SCHEMA "
199 " AND INFORMATION_SCHEMA.TABLES.TABLE_TYPE = "
204 QSqlQuery query =
m_db.exec(sql);
206 have_schema = query.value(0).toInt() > 1;
216 LOG(VB_GENERAL, LOG_ERR,
"Unable to connect to database!");
230 return m_db.isOpen();
241 LOG(VB_GENERAL, LOG_INFO,
"MySQL reconnected successfully");
251 m_db.exec(
"SET @@session.time_zone='+00:00'");
253 m_db.exec(
"SET @@session.sql_mode=''");
275 LOG(VB_GENERAL, LOG_CRIT,
276 "MDBManager exiting with connections still open");
281 cout<<
"m_DDCon: "<<
m_DDCon<<endl;
296 db =
m_inuse[QThread::currentThread()];
311 LOG(VB_DATABASE, LOG_INFO,
312 QString(
"New DB connection, total: %1").arg(
m_connCount));
324 m_inuse[QThread::currentThread()] = db;
340 if (db ==
m_inuse[QThread::currentThread()])
348 m_inuse[QThread::currentThread()] = NULL;
355 m_pool[QThread::currentThread()].push_front(db);
365 QMutexLocker locker(&
m_lock);
371 DBList::iterator it = list.begin();
373 uint purgedConnections = 0, totalConnections = 0;
375 while (it != list.end())
401 if (leaveOne && it == list.end() &&
402 purgedConnections > 0 &&
403 totalConnections == purgedConnections)
408 LOG(VB_GENERAL, LOG_INFO,
409 QString(
"New DB connection, total: %1").arg(
m_connCount));
413 LOG(VB_DATABASE, LOG_INFO,
"Deleting idle DB connection...");
415 LOG(VB_DATABASE, LOG_INFO,
"Done deleting idle DB connection.");
418 list.push_front(newDb);
420 if (purgedConnections)
422 LOG(VB_DATABASE, LOG_INFO,
423 QString(
"Purged %1 idle of %2 total DB connections.")
424 .arg(purgedConnections).arg(totalConnections));
436 LOG(VB_GENERAL, LOG_INFO,
"New static DB connection" + name);
439 (*dbcon)->OpenDatabase();
441 if (!
m_static_pool[QThread::currentThread()].contains(*dbcon))
461 m_pool[QThread::currentThread()].clear();
464 for (DBList::iterator it = list.begin(); it != list.end(); ++it)
466 LOG(VB_DATABASE, LOG_INFO,
467 "Closing DB connection named '" + (*it)->m_name +
"'");
475 while (!slist.isEmpty())
478 LOG(VB_DATABASE, LOG_INFO,
479 "Closing DB connection named '" + db->
m_name +
"'");
497 qi.
qsqldb = QSqlDatabase();
503 : QSqlQuery(QString::null, qi.qsqldb)
511 #ifdef DEBUG_QT4_PORT
522 if (dbmanager &&
m_db)
540 if (db->
m_db.hostName().isEmpty())
607 LOG(VB_GENERAL, LOG_ERR,
608 "MSqlQuery::exec(void) called without a prepared query.");
613 if (
random() < RAND_MAX / 50)
615 LOG(VB_GENERAL, LOG_INFO,
616 "MSqlQuery disconnecting DB to test reconnection logic");
625 LOG(VB_GENERAL, LOG_INFO,
"MySQL server disconnected");
634 if (!result && QSqlQuery::lastError().number() == 2006 &&
Reconnect())
641 bool has_null_strings =
false;
642 for (MSqlBindings::iterator it = tmp.begin(); it != tmp.end(); ++it)
644 if (it->type() != QVariant::String)
646 if (it->isNull() || it->toString().isNull())
648 has_null_strings =
true;
649 *it = QVariant(QString(
""));
652 if (has_null_strings)
659 LOG(VB_GENERAL, LOG_ERR,
660 QString(
"Original query failed, but resend with empty "
661 "strings in place of NULL strings worked. ") +
666 if (VERBOSE_LEVEL_CHECK(VB_DATABASE, LOG_DEBUG))
668 QString str = lastQuery();
672 if (!str.startsWith(
"INSERT INTO logging "))
682 str.replace(b.key(),
'\'' + b.value().toString() +
'\'');
685 LOG(VB_DATABASE, LOG_DEBUG,
686 QString(
"MSqlQuery::exec(%1) %2%3")
687 .arg(
m_db->MSqlDatabase::GetConnectionName()).arg(str)
688 .arg(isSelect() ? QString(
" <<<< Returns %1 row(s)")
689 .arg(
size()) : QString()));
708 LOG(VB_GENERAL, LOG_INFO,
"MySQL server disconnected");
717 if (!result && QSqlQuery::lastError().number() == 2006 &&
Reconnect())
720 LOG(VB_DATABASE, LOG_DEBUG,
721 QString(
"MSqlQuery::exec(%1) %2%3")
722 .arg(
m_db->MSqlDatabase::GetConnectionName()).arg(query)
723 .arg(isSelect() ? QString(
" <<<< Returns %1 row(s)")
724 .arg(
size()) : QString()));
730 int where,
bool relative)
const
732 if (result && VERBOSE_LEVEL_CHECK(VB_DATABASE, LOG_DEBUG))
735 QSqlRecord rec =
record();
737 for (
long int i = 0; i < rec.count(); i++)
742 str.append(rec.fieldName(i) +
" = " +
743 value(i).toString());
746 if (QString(
"seek")==
type)
748 LOG(VB_DATABASE, LOG_DEBUG,
749 QString(
"MSqlQuery::seek(%1,%2,%3) Result: \"%4\"")
750 .arg(
m_db->MSqlDatabase::GetConnectionName())
751 .arg(where).arg(relative)
756 LOG(VB_DATABASE, LOG_DEBUG,
757 QString(
"MSqlQuery::%1(%2) Result: \"%3\"")
758 .arg(type).arg(
m_db->MSqlDatabase::GetConnectionName())
772 return seekDebug(
"previous", QSqlQuery::previous(), 0,
false);
777 return seekDebug(
"first", QSqlQuery::first(), 0,
false);
787 return seekDebug(
"seek", QSqlQuery::seek(where, relative), where, relative);
800 #ifdef DEBUG_QT4_PORT
803 LOG(VB_GENERAL, LOG_DEBUG,
804 QString(
"\n\nQuery contains bind value \"%1\" twice:\n\n\n")
822 LOG(VB_GENERAL, LOG_INFO,
"MySQL server disconnected");
831 if (!ok && QSqlQuery::lastError().number() == 2006 &&
Reconnect())
834 if (!ok && !(
GetMythDB()->SuppressDBMessages()))
836 LOG(VB_GENERAL, LOG_ERR,
837 QString(
"Error preparing query: %1").arg(query));
838 LOG(VB_GENERAL, LOG_ERR,
851 bool isOpen = db->
isOpen();
859 #ifdef DEBUG_QT4_PORT
864 LOG(VB_GENERAL, LOG_ERR,
"Trying to bind a value to placeholder " +
865 placeholder +
" without occurrence in the prepared query."
877 MSqlBindings::const_iterator it;
878 for (it = bindings.begin(); it != bindings.end(); ++it)
905 MSqlBindings::Iterator it;
906 for (it = addfrom.begin(); it != addfrom.end(); ++it)
908 output.insert(it.key(), it.value());
913 Holder(
const QString& hldr = QString::null,
int pos = -1 )
929 QRegExp rx(QString::fromLatin1(
"'[^']*'|:([a-zA-Z0-9_]+)"));
931 QVector<Holder> holders;
934 while ((i = rx.indexIn(q, i)) != -1)
936 if (!rx.cap(1).isEmpty())
937 holders.append(
Holder(rx.cap(0), i));
938 i += rx.matchedLength();
944 for (i = (
int)holders.count() - 1; i >= 0; --i)
946 holder = holders[(
uint)i].holderName;
947 val = bindings[holder];
948 QSqlField f(
"", val.type());
954 query = query.replace((
uint)holders[(
uint)i].holderPos, holder.length(),
955 result.
driver()->formatValue(f));