/** * @RDE_HEADER@ * Template for 'real' structures including insert/update/delete functions for db * $Id$ * $HeadURL$ * $Author$ */ {% autoescape off %} // filename: {{ namespace_abbr }}_db_impl.cpp #include "{{ namespace_abbr }}_db_impl.h" {% if custom_db_procs %} #include <{{ include_prefix }}/{{ namespace_abbr }}_db_impl_custom.h> {% endif %} #include #include #include #include #include #include #include namespace {{ namespace }} { QString qVariantToJsonString(const QVariant &value) { return value.isNull() ? QStringLiteral("{}") : value.toString(); } QString fixupEmptyJsonString(const QString &str) { return str.isEmpty() ? QStringLiteral("{}") : str; } // DatabaseInterface std::shared_ptr DatabaseInterface::create(int exerciseId) { {% if custom_db_procs %} return std::make_shared(exerciseId); {% else %} return std::make_shared(exerciseId); {% endif %} } DatabaseInterfaceImpl::DatabaseInterfaceImpl(int exerciseId) : m_query(nullptr) , m_exerciseId(exerciseId) , m_bEmitMessageOnError(true) , m_bCanHandleSchemas(true) , m_ownDatabaseConnection(true) , m_logger(getLogger("Db")) {} DatabaseInterfaceImpl::~DatabaseInterfaceImpl() { m_query = nullptr; {% if has_db_notifications %} QSqlDriver *driver = m_dbConnection.driver(); if (driver && m_dbConnection.isOpen()) { {% for cpp_struct in cpp_structs %}{% for db_notify in cpp_struct.dbNotifications %} driver->unsubscribeFromNotification(QStringLiteral("{{ db_notify }}"));{% endfor %}{% endfor %} } {% endif %} if (m_ownDatabaseConnection && m_dbConnection.isOpen()) m_dbConnection.close(); } bool DatabaseInterfaceImpl::init(const QSqlDatabase &dbConnection) { m_dbConnection = dbConnection; m_ownDatabaseConnection = false; return initInternal(); } bool DatabaseInterfaceImpl::init(const QString &dbUser, const QString &dbPasswd, const QString &dbDriver, const QString &dbHost, const QString &dbName) { m_ownDatabaseConnection = true; m_dbConnection = DBConnection::open(m_logger, dbUser, dbPasswd, dbDriver, dbHost, dbName, schemaName()); return initInternal(); } bool DatabaseInterfaceImpl::initInternal() { QSqlDriver *driver = m_dbConnection.driver(); if (!driver) { WARNING_LOG(m_logger) << "No SQL driver loaded - no database available!"; return false; } const QString driverName = m_dbConnection.driverName(); DEBUG_LOG(m_logger) << "Connected to database " << m_dbConnection.databaseName() << "@" << m_dbConnection.hostName() << ", schema: " << schemaName() << ", used driver: " << driverName; if (!m_dbConnection.isOpen()) { WARNING_LOG(m_logger) << "Database connection is no open - can not initialize database interface"; return false; } if (driverName == QLatin1String("QSQLITE")) m_bCanHandleSchemas = false; {% if has_db_notifications %} if (!driver->hasFeature(QSqlDriver::EventNotifications)) { WARNING_LOG(m_logger) << "Can not subscribe to notifications - sqldriver does not support this feature!"; } else { connect(driver, QOverload::of(&QSqlDriver::notification), this, &DatabaseInterfaceImpl::onNotification); {% for cpp_struct in cpp_structs %}{% for db_notify in cpp_struct.dbNotifications %} driver->subscribeToNotification(QStringLiteral("{{ db_notify }}"));{% endfor %}{% endfor %} } {% endif %} m_query = std::unique_ptr(new NSqlQuery(m_dbConnection, m_logger)); return true; } QString DatabaseInterfaceImpl::schemaName() const { if (!m_bCanHandleSchemas) return QString(); if (m_exerciseId <= 0) return QStringLiteral("{{ namespace_abbr }}"); return DBCommon::getExerciseSchemaName(m_exerciseId); } QString DatabaseInterfaceImpl::dbUser() const { if (m_exerciseId > 0) return QStringLiteral("ets_ex_00"); else return QStringLiteral("ets_") + schemaName(); } void DatabaseInterfaceImpl::setEmitMessageOnError(bool bEmit) { m_bEmitMessageOnError = bEmit; } QString DatabaseInterfaceImpl::getTableName(const QString &tableName) const { if (!m_bCanHandleSchemas) return tableName; if (m_exerciseId > 0) return DBCommon::getExerciseTableName(tableName, m_exerciseId); return QStringLiteral("{{ namespace_abbr }}.") + tableName; } QSqlError DatabaseInterfaceImpl::getLastError() const { return m_lastError; } {% if has_db_notifications %} void DatabaseInterfaceImpl::onNotification(const QString &name, QSqlDriver::NotificationSource source, const QVariant &payload) { DEBUG_LOG(m_logger) << "Notification source = " << source; // no need to emit notification signals if (source == QSqlDriver::SelfSource) return; // search coresponding signal {% for cpp_struct in cpp_structs %}{% for db_notify in cpp_struct.dbNotifications %} if (name == QLatin1String("{{ db_notify }}")) { emit {{ db_notify }}(payload); }{% endfor %}{% endfor %} } {% endif %} {% for cpp_struct in cpp_structs %} // // Struct: Database::{{ cpp_struct.name }} // bool DatabaseInterfaceImpl::insert(Database::{{ cpp_struct.name }} &data) { SqlQueryJanitor janitor(m_query); {% if cpp_struct.insertStructures|length > 1 %} DBTransaction transaction(m_dbConnection); {% endif %} {% for insertStruct in cpp_struct.insertStructures %} { const QString tableName(getTableName(QStringLiteral("{{ insertStruct.name }}"))); QString keyColumnInsertKey; QString keyColumnInsertVal; {% if forloop.first and cpp_struct.primaryKey.dbHasSequence %} const bool bInsertWithKey = data.{{cpp_struct.primaryKey.cppMemberName}} != {{cpp_struct.primaryKey.cppDefault}}; if (bInsertWithKey) { keyColumnInsertKey = QStringLiteral("{{ insertStruct.primaryKey.dbColumnName }}, "); keyColumnInsertVal = QStringLiteral(" :{{ insertStruct.primaryKey.dbColumnName }}, "); } {% endif %} const QString stmt(QStringLiteral("INSERT INTO ") + tableName + QStringLiteral(" (") + keyColumnInsertKey + QStringLiteral("{% for row in insertStruct.member %} {{ row.dbColumnName }}{% if not forloop.last %}, {% endif %}{% endfor %}" " ) VALUES (") + keyColumnInsertVal + QStringLiteral("{% for row in insertStruct.member %}:{{ row.dbColumnName }}{% if not forloop.last %}, {% endif %}{% endfor %} )")); if (!m_query->prepare(stmt)) { m_lastError = m_query->lastError(); return false; } {% if forloop.first and cpp_struct.primaryKey.dbHasSequence %} if (bInsertWithKey) m_query->bindValue(QStringLiteral(":{{ insertStruct.primaryKey.dbColumnName }}"), data.{{ insertStruct.serialMember.cppMemberName }}); {% endif %} {% for row in insertStruct.member %} m_query->bindValue(QStringLiteral(":{{ row.dbColumnName }}"), {{ row.cppToQvPre }}data.{{ row.cppMemberName }}{{ row.cppToQvPost }}); {% endfor %} if (!m_query->exec(m_bEmitMessageOnError)) { m_lastError = m_query->lastError(); return false; } {% if insertStruct.serialMember.cppMemberName %} {% if forloop.first and cpp_struct.primaryKey.dbHasSequence %} if (data.{{cpp_struct.primaryKey.cppMemberName}} == {{cpp_struct.primaryKey.cppDefault}}) data.{{ insertStruct.serialMember.cppMemberName }} = m_query->lastInsertId(){{ insertStruct.serialMember.cppFromQvPost }}; {% else %} data.{{ insertStruct.serialMember.cppMemberName }} = m_query->lastInsertId(){{ insertStruct.serialMember.cppFromQvPost }}; {% endif %} {% if insertStruct.baseId.cppMemberName %} data.{{ insertStruct.baseId.cppMemberName }} = data.{{ insertStruct.serialMember.cppMemberName }}; {% endif %} {% endif %} } {% endfor %} {% if cpp_struct.insertStructures|length > 1 %} transaction.commit(); {% endif %} return true; } bool DatabaseInterfaceImpl::upsert(Database::{{ cpp_struct.name }} &data) { SqlQueryJanitor janitor(m_query); {% if cpp_struct.insertStructures|length > 1 %} DBTransaction transaction(m_dbConnection); {% endif %} {% for insertStruct in cpp_struct.insertStructures %} { const QString tableName(getTableName(QStringLiteral("{{ insertStruct.name }}"))); QString keyColumnInsertKey; QString keyColumnInsertKeyConflict; QString keyColumnInsertVal; {% if forloop.first and cpp_struct.primaryKey.dbHasSequence %} const bool bInsertWithKey = true; keyColumnInsertVal = QStringLiteral(" :{{ insertStruct.primaryKey.dbColumnName }}, "); keyColumnInsertKey = QStringLiteral("{{ insertStruct.primaryKey.dbColumnName }}, "); {% endif %} keyColumnInsertKeyConflict = QStringLiteral("{{ insertStruct.primaryKey.dbColumnName }} "); const QString stmt(QStringLiteral("INSERT INTO ") + tableName + QStringLiteral(" (") + keyColumnInsertKey + QStringLiteral("{% for row in insertStruct.member %} {{ row.dbColumnName }}{% if not forloop.last %}, {% endif %}{% endfor %}" " ) VALUES (") + keyColumnInsertVal + QStringLiteral("{% for row in insertStruct.member %}:{{ row.dbColumnName }}{% if not forloop.last %}, {% endif %}{% endfor %} )") + QStringLiteral(" ON CONFLICT (") + keyColumnInsertKeyConflict + QStringLiteral(") DO UPDATE ") + QStringLiteral(" SET" " {% for row in insertStruct.member %}{{ row.dbColumnName }} = :{{ row.dbColumnName }}{% if not forloop.last %}, {% endif %}{% endfor %}" " WHERE excluded.{{ insertStruct.primaryKey.dbColumnName }} = :{{ insertStruct.primaryKey.dbColumnName }}")); if (!m_query->prepare(stmt)) { m_lastError = m_query->lastError(); return false; } {% if forloop.first and cpp_struct.primaryKey.dbHasSequence %} if (bInsertWithKey) m_query->bindValue(QStringLiteral(":{{ insertStruct.primaryKey.dbColumnName }}"), data.{{ insertStruct.serialMember.cppMemberName }}); {% endif %} {% for row in insertStruct.member %} m_query->bindValue(QStringLiteral(":{{ row.dbColumnName }}"), {{ row.cppToQvPre }}data.{{ row.cppMemberName }}{{ row.cppToQvPost }}); {% endfor %} if (!m_query->exec(m_bEmitMessageOnError)) { m_lastError = m_query->lastError(); return false; } {% if insertStruct.serialMember.cppMemberName %} {% if forloop.first and cpp_struct.primaryKey.dbHasSequence %} if (data.{{cpp_struct.primaryKey.cppMemberName}} == {{cpp_struct.primaryKey.cppDefault}}) data.{{ insertStruct.serialMember.cppMemberName }} = m_query->lastInsertId(){{ insertStruct.serialMember.cppFromQvPost }}; {% else %} data.{{ insertStruct.serialMember.cppMemberName }} = m_query->lastInsertId(){{ insertStruct.serialMember.cppFromQvPost }}; {% endif %} {% if insertStruct.baseId.cppMemberName %} data.{{ insertStruct.baseId.cppMemberName }} = data.{{ insertStruct.serialMember.cppMemberName }}; {% endif %} {% endif %} } {% endfor %} {% if cpp_struct.insertStructures|length > 1 %} transaction.commit(); {% endif %} return true; } bool DatabaseInterfaceImpl::update(const Database::{{ cpp_struct.name }} &data) { SqlQueryJanitor janitor(m_query); {% if cpp_struct.insertStructures|length > 1 %} DBTransaction transaction(m_dbConnection); {% endif %} {% for insertStruct in cpp_struct.insertStructures %} { const QString tableName(getTableName(QStringLiteral("{{ insertStruct.name }}"))); const QString stmt(QStringLiteral("UPDATE ") + tableName + QStringLiteral(" SET" " {% for row in insertStruct.member %}{{ row.dbColumnName }} = :{{ row.dbColumnName }}{% if not forloop.last %}, {% endif %}{% endfor %}" " WHERE {{ insertStruct.primaryKey.dbColumnName }} = :{{ insertStruct.primaryKey.dbColumnName }}")); if (!m_query->prepare(stmt)) { m_lastError = m_query->lastError(); return false; } {% for row in insertStruct.member %} m_query->bindValue(QStringLiteral(":{{ row.dbColumnName }}"), {{ row.cppToQvPre }}data.{{ row.cppMemberName }}{{ row.cppToQvPost }}); {% endfor %} {% if insertStruct.serialMember.cppMemberName %} m_query->bindValue(QStringLiteral(":{{ insertStruct.primaryKey.dbColumnName }}"), data.{{ insertStruct.serialMember.cppMemberName }}); {% endif %} if (!m_query->exec(m_bEmitMessageOnError)) { m_lastError = m_query->lastError(); return false; } } {% endfor %} {% if cpp_struct.insertStructures|length > 1 %} transaction.commit(); {% endif %} return true; } {% if cpp_struct.insertStructures|length == 1 %} // current only implemented for 'plain' structures with only one affected table bool DatabaseInterfaceImpl::insert(std::vector &cont) { if (cont.empty()) return true; {% for insertStruct in cpp_struct.insertStructures %} { const QString tableName(getTableName(QStringLiteral("{{ insertStruct.name }}"))); QString keyColumnInsertKey; QString keyColumnInsertVal; {% if forloop.first and cpp_struct.primaryKey.dbHasSequence %} const bool bInsertWithKey = cont[0].{{cpp_struct.primaryKey.cppMemberName}} != {{cpp_struct.primaryKey.cppDefault}}; // the first element determines the stmt to be used if (bInsertWithKey) { keyColumnInsertKey = QStringLiteral("{{ insertStruct.primaryKey.dbColumnName }}, "); keyColumnInsertVal = QStringLiteral(" :{{ insertStruct.primaryKey.dbColumnName }}, "); } {% endif %} const QString stmt(QStringLiteral("INSERT INTO ") + tableName + QStringLiteral(" (") + keyColumnInsertKey + QStringLiteral("{% for row in insertStruct.member %} {{ row.dbColumnName }}{% if not forloop.last %}, {% endif %}{% endfor %}" " ) VALUES (") + keyColumnInsertVal + QStringLiteral("{% for row in insertStruct.member %}:{{ row.dbColumnName }}{% if not forloop.last %}, {% endif %}{% endfor %} )")); { SqlQueryJanitor janitor(m_query); if (!m_query->prepare(stmt)) { m_lastError = m_query->lastError(); return false; } for (auto &data : cont) { {% if forloop.first and cpp_struct.primaryKey.dbHasSequence %} if (bInsertWithKey) m_query->bindValue(QStringLiteral(":{{ insertStruct.primaryKey.dbColumnName }}"), data.{{ insertStruct.serialMember.cppMemberName }}); {% endif %} {% for row in insertStruct.member %} m_query->bindValue(QStringLiteral(":{{ row.dbColumnName }}"), {{ row.cppToQvPre }}data.{{ row.cppMemberName }}{{ row.cppToQvPost }}); {% endfor %} if (!m_query->exec(m_bEmitMessageOnError)) { m_lastError = m_query->lastError(); return false; } {% if insertStruct.serialMember.cppMemberName %} if (data.{{cpp_struct.primaryKey.cppMemberName}} == {{cpp_struct.primaryKey.cppDefault}}) data.{{ insertStruct.serialMember.cppMemberName }} = m_query->lastInsertId(){{ insertStruct.serialMember.cppFromQvPost }}; {% endif %} } } {% if forloop.first and cpp_struct.primaryKey.dbHasSequence %} if (bInsertWithKey) fixUpSequence{{ cpp_struct.nameCc }}(); {% endif %} } {% endfor %} return true; } bool DatabaseInterfaceImpl::upsert(std::vector &cont) { if (cont.empty()) return true; {% for insertStruct in cpp_struct.insertStructures %} { const QString tableName(getTableName(QStringLiteral("{{ insertStruct.name }}"))); QString keyColumnInsertKey; QString keyColumnInsertKeyConflict; QString keyColumnInsertVal; {% if forloop.first and cpp_struct.primaryKey.dbHasSequence %} const bool bInsertWithKey = true; keyColumnInsertVal = QStringLiteral(" :{{ insertStruct.primaryKey.dbColumnName }}, "); keyColumnInsertKey = QStringLiteral("{{ insertStruct.primaryKey.dbColumnName }}, "); {% endif %} // the first element determines the stmt to be used keyColumnInsertKeyConflict = QStringLiteral("{{ insertStruct.primaryKey.dbColumnName }} "); const QString stmt(QStringLiteral("INSERT INTO ") + tableName + QStringLiteral(" (") + keyColumnInsertKey + QStringLiteral("{% for row in insertStruct.member %} {{ row.dbColumnName }}{% if not forloop.last %}, {% endif %}{% endfor %}" " ) VALUES (") + keyColumnInsertVal + QStringLiteral("{% for row in insertStruct.member %}:{{ row.dbColumnName }}{% if not forloop.last %}, {% endif %}{% endfor %} )") + QStringLiteral(" ON CONFLICT (") + keyColumnInsertKeyConflict + QStringLiteral(") DO UPDATE ") + QStringLiteral(" SET" " {% for row in insertStruct.member %}{{ row.dbColumnName }} = :{{ row.dbColumnName }}{% if not forloop.last %}, {% endif %}{% endfor %}" " WHERE excluded.{{ insertStruct.primaryKey.dbColumnName }} = :{{ insertStruct.primaryKey.dbColumnName }}")); { SqlQueryJanitor janitor(m_query); if (!m_query->prepare(stmt)) { m_lastError = m_query->lastError(); return false; } for (auto &data : cont) { {% if forloop.first and cpp_struct.primaryKey.dbHasSequence %} if (bInsertWithKey) m_query->bindValue(QStringLiteral(":{{ insertStruct.primaryKey.dbColumnName }}"), data.{{ insertStruct.serialMember.cppMemberName }}); {% endif %} {% for row in insertStruct.member %} m_query->bindValue(QStringLiteral(":{{ row.dbColumnName }}"), {{ row.cppToQvPre }}data.{{ row.cppMemberName }}{{ row.cppToQvPost }}); {% endfor %} if (!m_query->exec(m_bEmitMessageOnError)) { m_lastError = m_query->lastError(); return false; } {% if insertStruct.serialMember.cppMemberName %} if (data.{{cpp_struct.primaryKey.cppMemberName}} == {{cpp_struct.primaryKey.cppDefault}}) data.{{ insertStruct.serialMember.cppMemberName }} = m_query->lastInsertId(){{ insertStruct.serialMember.cppFromQvPost }}; {% endif %} } } {% if forloop.first and cpp_struct.primaryKey.dbHasSequence %} if (bInsertWithKey) fixUpSequence{{ cpp_struct.nameCc }}(); {% endif %} } {% endfor %} return true; } // current only implemented for 'plain' structures with only one affected table bool DatabaseInterfaceImpl::update(const std::vector &cont) { if (cont.empty()) return true; {% for insertStruct in cpp_struct.insertStructures %} { const QString tableName(getTableName(QStringLiteral("{{ insertStruct.name }}"))); const QString stmt(QStringLiteral("UPDATE ") + tableName + QStringLiteral(" SET" " {% for row in insertStruct.member %}{{ row.dbColumnName }} = :{{ row.dbColumnName }}{% if not forloop.last %}, {% endif %}{% endfor %}" " WHERE {{ insertStruct.primaryKey.dbColumnName }} = :{{ insertStruct.primaryKey.dbColumnName }}")); { SqlQueryJanitor janitor(m_query); if (!m_query->prepare(stmt)) { m_lastError = m_query->lastError(); return false; } for (const auto &data : cont) { {% for row in insertStruct.member %} m_query->bindValue(QStringLiteral(":{{ row.dbColumnName }}"), {{ row.cppToQvPre }}data.{{ row.cppMemberName }}{{ row.cppToQvPost }}); {% endfor %} {% if insertStruct.serialMember.cppMemberName %} m_query->bindValue(QStringLiteral(":{{ insertStruct.primaryKey.dbColumnName }}"), data.{{ insertStruct.serialMember.cppMemberName }}); {% endif %} if (!m_query->exec(m_bEmitMessageOnError)) { m_lastError = m_query->lastError(); return false; } } } } {% endfor %} return true; } {% endif %} bool DatabaseInterfaceImpl::select(QVector &dataVec) { SqlQueryJanitor janitor(m_query); const auto cb =[&dataVec] (const Database::{{ cpp_struct.name }} &data) { dataVec.push_back(data); }; return selectPrepareInternal{{ cpp_struct.name }}(QString()) && selectFetchInternal{{ cpp_struct.name }}(cb); } bool DatabaseInterfaceImpl::select(const std::function &cb) { SqlQueryJanitor janitor(m_query); return selectPrepareInternal{{ cpp_struct.name }}(QString()) && selectFetchInternal{{ cpp_struct.name }}(cb); } {% for fk in cpp_struct.selectRemoveMember %} bool DatabaseInterfaceImpl::selectBy{{ fk.cppMemberNameCc }}(QVector &dataVec, const {{ fk.cppType }} &{{ fk.cppMemberName }}, const QString &orderBy) { SqlQueryJanitor janitor(m_query); if (!selectPrepareInternal{{ cpp_struct.name }}(QStringLiteral(" WHERE {{ fk.dbColumnName }} = :{{ fk.dbColumnName }}") + orderBy)) { ERROR_LOG(m_logger) << "Error preparing query: " << m_query->lastError().text(); m_lastError = m_query->lastError(); return false; } m_query->bindValue(QStringLiteral(":{{ fk.dbColumnName }}"), {{ fk.cppToQvPre }}{{ fk.cppMemberName }}{{ fk.cppToQvPost }}); const auto cb =[&dataVec] (const Database::{{ cpp_struct.name }} &data) { dataVec.push_back(data); }; return selectFetchInternal{{ cpp_struct.name }}(cb); } bool DatabaseInterfaceImpl::selectBy{{ fk.cppMemberNameCc }}(const std::function &cb, const {{ fk.cppType }} &{{ fk.cppMemberName }}, const QString &orderBy) { SqlQueryJanitor janitor(m_query); if (!selectPrepareInternal{{ cpp_struct.name }}(QStringLiteral(" WHERE {{ fk.dbColumnName }} = :{{ fk.dbColumnName }}") + orderBy)) { ERROR_LOG(m_logger) << "Error preparing query: " << m_query->lastError().text(); m_lastError = m_query->lastError(); return false; } m_query->bindValue(QStringLiteral(":{{ fk.dbColumnName }}"), {{ fk.cppToQvPre }}{{ fk.cppMemberName }}{{ fk.cppToQvPost }}); return selectFetchInternal{{ cpp_struct.name }}(cb); } {% endfor %} bool DatabaseInterfaceImpl::selectPrepareInternal{{ cpp_struct.name }}(const QString &where) { const QString tableName(getTableName(QStringLiteral("{{ cpp_struct.viewTableName }}"))); const QString stmt(QStringLiteral("SELECT {% for row in cpp_struct.viewMember %}{{ row.dbColumnNameView }}{% if not forloop.last %}, {% endif %}{% endfor %}" " FROM ") + tableName + where); return m_query->prepare(stmt); } bool DatabaseInterfaceImpl::selectFetchInternal{{ cpp_struct.name }}(const std::function &cb) { if (!m_query->exec(m_bEmitMessageOnError)) { m_lastError = m_query->lastError(); return false; } Database::{{ cpp_struct.name }} data; while (m_query->next()) { int i = 0; {% for row in cpp_struct.viewMember %} data.{{ row.cppMemberName }}{{ row.cppFromQvPre1 }} = {{ row.cppFromQvPre2 }}m_query->value(i++){{ row.cppFromQvPost }};{% endfor %} cb(data); } return true; } bool DatabaseInterfaceImpl::select{{ cpp_struct.name }}({{ cpp_struct.primaryKey.cppType }} {{ cpp_struct.primaryKey.cppMemberName }}, Database::{{ cpp_struct.name }} &data) { SqlQueryJanitor janitor(m_query); int iCnt = 0; const auto cb =[&data, &iCnt] (const Database::{{ cpp_struct.name }} &content) { data = content; ++iCnt; }; const QString where = QStringLiteral(" WHERE {{ cpp_struct.primaryKey.dbColumnName }} = %1").arg({{ cpp_struct.primaryKey.cppMemberName }}); if (!selectPrepareInternal{{ cpp_struct.name }}(where) || !selectFetchInternal{{ cpp_struct.name }}(cb)) return false; return (iCnt == 1); } bool DatabaseInterfaceImpl::remove{{ cpp_struct.name }}({{ cpp_struct.primaryKey.cppType }} {{ cpp_struct.primaryKey.cppMemberName }}) { SqlQueryJanitor janitor(m_query); const QString tableName(getTableName(QStringLiteral("{{ cpp_struct.primaryKey.dbTableName }}"))); const QString stmt(QStringLiteral("DELETE FROM ") + tableName + QStringLiteral(" WHERE {{ cpp_struct.primaryKey.dbColumnName }} = ") + QString::number({{ cpp_struct.primaryKey.cppMemberName }})); if (!m_query->exec(stmt, m_bEmitMessageOnError)) { m_lastError = m_query->lastError(); return false; } return true; } {% if cpp_struct.deleteWithoutPkAllowed %} {% for fk in cpp_struct.selectRemoveMember %} bool DatabaseInterfaceImpl::remove{{ cpp_struct.nameCc }}By{{ fk.cppMemberNameCc }}(const {{ fk.cppType }} &{{ fk.cppMemberName }}) { SqlQueryJanitor janitor(m_query); const QString tableName(getTableName(QStringLiteral("{{ cpp_struct.primaryKey.dbTableName }}"))); const QString stmt(QStringLiteral("DELETE FROM ") + tableName + QStringLiteral(" WHERE {{ fk.dbColumnName }} = :{{ fk.cppMemberName }}")); if (!m_query->prepare(stmt)) { ERROR_LOG(m_logger) << "Error preparing query: " << m_query->lastError().text(); m_lastError = m_query->lastError(); return false; } m_query->bindValue(QStringLiteral(":{{ fk.cppMemberName }}"), {{ fk.cppToQvPre }}{{ fk.cppMemberName }}{{ fk.cppToQvPost }}); return m_query->exec(m_bEmitMessageOnError); } {% endfor %} {% endif %} bool DatabaseInterfaceImpl::fixUpSequence{{ cpp_struct.nameCc }}() { SqlQueryJanitor janitor(m_query); const QString tableName(getTableName(QStringLiteral("{{ cpp_struct.primaryKey.dbTableName }}"))); const QString stmt(QStringLiteral("SELECT setval('") + tableName + QStringLiteral("_{{ cpp_struct.primaryKey.dbColumnName }}_seq', COALESCE((SELECT MAX({{ cpp_struct.primaryKey.dbColumnName }})+1 FROM ") + tableName + QStringLiteral("), 1),false)")); if (!m_query->exec(stmt, m_bEmitMessageOnError)) { m_lastError = m_query->lastError(); return false; } return true; } bool DatabaseInterfaceImpl::truncate{{ cpp_struct.nameCc }}() { SqlQueryJanitor janitor(m_query); const QString tableName(getTableName(QStringLiteral("{{ cpp_struct.primaryKey.dbTableName }}"))); const QString stmt(QStringLiteral("TRUNCATE TABLE ") + tableName + QStringLiteral(" CASCADE")); if (!m_query->exec(stmt, m_bEmitMessageOnError)) { m_lastError = m_query->lastError(); return false; } return true; } // Database::{{ cpp_struct.name }} end {% endfor %} {% for ds in data_structs %} bool DatabaseInterfaceImpl::select(QVector &dataVec) { SqlQueryJanitor janitor(m_query); const QString tableName(getTableName(QStringLiteral("{{ ds.viewTableName }}"))); const QString stmt(QStringLiteral("SELECT {% for row in ds.viewMember %}{{ row.dbColumnName }}{% if not forloop.last %}, {% endif %}{% endfor %}" " FROM ") + tableName); if (!m_query->exec(stmt, m_bEmitMessageOnError)) { m_lastError = m_query->lastError(); return false; } Database::{{ ds.name }} data; while (m_query->next()) { int i = 0; {% for row in ds.member %} data.{{ row.cppMemberName }}{{ row.cppFromQvPre1 }} = {{ row.cppFromQvPre2 }}m_query->value(i++){{ row.cppFromQvPost }};{% endfor %} dataVec.append(data); } return true; } {% endfor %} } // namespace {{ namespace }} {% endautoescape %}