1 #pragma once 2 3 #include <QtDebug> 4 #include <QtSql> 5 6 7 #define LOG_FAILED_QUERY(query) qWarning() << __FILE__ << __LINE__ << "FAILED QUERY [" \ 8 << (query).executedQuery() << "]" << (query).lastError() 9 10 class ScopedTransaction { 11 public: ScopedTransaction(const QSqlDatabase & database)12 explicit ScopedTransaction(const QSqlDatabase& database) : 13 m_database(database), 14 m_active(false) { 15 if (!transaction()) { 16 qDebug() << "ERROR: Could not start transaction on" 17 << m_database.connectionName(); 18 } 19 } ~ScopedTransaction()20 virtual ~ScopedTransaction() { 21 if (m_active) { 22 rollback(); 23 } 24 } active()25 bool active() const { 26 return m_active; 27 } transaction()28 bool transaction() { 29 if (m_active) { 30 qDebug() << "WARNING: Transaction already active and received transaction() request on" 31 << m_database.connectionName(); 32 return false; 33 } 34 m_active = m_database.transaction(); 35 return m_active; 36 } commit()37 bool commit() { 38 if (!m_active) { 39 qDebug() << "WARNING: commit() called on inactive transaction for" 40 << m_database.connectionName(); 41 return false; 42 } 43 bool result = m_database.commit(); 44 qDebug() << "Committing transaction on" 45 << m_database.connectionName() 46 << "result:" << result; 47 m_active = false; 48 return result; 49 } rollback()50 bool rollback() { 51 if (!m_active) { 52 qDebug() << "WARNING: rollback() called on inactive transaction for" 53 << m_database.connectionName(); 54 return false; 55 } 56 bool result = m_database.rollback(); 57 qDebug() << "Rolling back transaction on" 58 << m_database.connectionName() 59 << "result:" << result; 60 m_active = false; 61 return result; 62 } 63 private: 64 QSqlDatabase m_database; 65 bool m_active; 66 }; 67 68 class FieldEscaper final { 69 public: FieldEscaper(const QSqlDatabase & database)70 FieldEscaper(const QSqlDatabase& database) 71 : m_database(database), 72 m_stringField("string", QVariant::String) { 73 } 74 75 // Escapes a string for use in a SQL query by wrapping with quotes and 76 // escaping embedded quote characters. escapeString(const QString & escapeString)77 QString escapeString(const QString& escapeString) const { 78 m_stringField.setValue(escapeString); 79 return m_database.driver()->formatValue(m_stringField); 80 } 81 escapeStrings(const QStringList & escapeStrings)82 QStringList escapeStrings(const QStringList& escapeStrings) const { 83 QStringList result = escapeStrings; 84 escapeStringsInPlace(&result); 85 return result; 86 } 87 88 private: escapeStringsInPlace(QStringList * pEscapeStrings)89 void escapeStringsInPlace(QStringList* pEscapeStrings) const { 90 QMutableStringListIterator it(*pEscapeStrings); 91 while (it.hasNext()) { 92 it.setValue(escapeString(it.next())); 93 } 94 } 95 96 QSqlDatabase m_database; 97 mutable QSqlField m_stringField; 98 }; 99