#ifndef GRADIDO_LOGIN_SERVER_MODEL_INTERFACE_INCLUDE #define GRADIDO_LOGIN_SERVER_MODEL_INTERFACE_INCLUDE #include "Poco/Data/Session.h" #include "../../SingletonManager/ConnectionManager.h" #include "../../lib/MultithreadContainer.h" #include "../../tasks/CPUTask.h" #include "../../MySQL/MysqlTable.h" #include "../../ServerConfig.h" //using namespace Poco::Data::Keywords; namespace model { namespace table { enum MysqlConditionType { MYSQL_CONDITION_AND, MYSQL_CONDITION_OR }; class ModelBase : public UniLib::lib::MultithreadContainer, public ErrorList { public: ModelBase(int id) :mID(id), mReferenceCount(1) {} ModelBase() : mID(0), mReferenceCount(1) {} virtual ~ModelBase(); virtual const char* getTableName() = 0; virtual std::string toString() = 0; template size_t updateIntoDB(const std::string& fieldName, const T& fieldValue ); template size_t loadFromDB(const std::string& fieldName, const T& fieldValue); template std::vector loadFromDB(const std::string& fieldName, const WhereFieldType& fieldValue, int expectedResults = 0); template size_t loadFromDB(const std::vector& fieldNames, const T1& field1Value, const T2& field2Value, MysqlConditionType conditionType = MYSQL_CONDITION_AND); bool insertIntoDB(bool loadId); bool deleteFromDB(); inline void setID(int id) { lock(); mID = id; unlock(); } inline int getID() { lock(); int id = mID; unlock(); return id; } static Poco::DateTime parseElopageDate(std::string dateString); // for poco auto ptr void duplicate(); void release(); protected: virtual Poco::Data::Statement _loadIdFromDB(Poco::Data::Session session) = 0; virtual Poco::Data::Statement _loadFromDB(Poco::Data::Session session, const std::string& fieldName) = 0; virtual Poco::Data::Statement _loadFromDB(Poco::Data::Session session, const std::vector& fieldNames, MysqlConditionType conditionType = MYSQL_CONDITION_AND); virtual Poco::Data::Statement _loadMultipleFromDB(Poco::Data::Session session, const std::string& fieldName); virtual Poco::Data::Statement _insertIntoDB(Poco::Data::Session session) = 0; int mID; // for poco auto ptr int mReferenceCount; }; template size_t ModelBase::loadFromDB(const std::string& fieldName, const T& fieldValue) { auto cm = ConnectionManager::getInstance(); Poco::Data::Statement select = _loadFromDB(cm->getConnection(CONNECTION_MYSQL_LOGIN_SERVER), fieldName); select, Poco::Data::Keywords::useRef(fieldValue); size_t resultCount = 0; try { resultCount = select.execute(); } catch (Poco::Exception& ex) { lock(); addError(new ParamError(getTableName(), "mysql error by selecting", ex.displayText().data())); addError(new ParamError(getTableName(), "field name for select: ", fieldName.data())); unlock(); } return resultCount; } template std::vector ModelBase::loadFromDB(const std::string& fieldName, const WhereFieldType& fieldValue, int expectedResults) { printf("ModelBase::loadFromDB multi\n"); std::vector results; return results; if (expectedResults > 0) { results.reserve(expectedResults); } auto cm = ConnectionManager::getInstance(); Poco::Data::Statement select = _loadMultipleFromDB(cm->getConnection(CONNECTION_MYSQL_LOGIN_SERVER), fieldName); select, Poco::Data::Keywords::into(results), Poco::Data::Keywords::useRef(fieldValue); size_t resultCount = 0; try { resultCount = select.execute(); } catch (Poco::Exception& ex) { lock(); addError(new ParamError(getTableName(), "mysql error by multi selecting", ex.displayText().data())); addError(new ParamError(getTableName(), "field name for select: ", fieldName.data())); unlock(); } return results; } template size_t ModelBase::loadFromDB(const std::vector& fieldNames, const T1& field1Value, const T2& field2Value, MysqlConditionType conditionType/* = MYSQL_CONDITION_AND*/) { auto cm = ConnectionManager::getInstance(); Poco::Data::Statement select = _loadFromDB(cm->getConnection(CONNECTION_MYSQL_LOGIN_SERVER), fieldNames, conditionType); select, Poco::Data::Keywords::useRef(field1Value), Poco::Data::Keywords::useRef(field2Value); size_t resultCount = 0; try { resultCount = select.execute(); } catch (Poco::Exception& ex) { lock(); addError(new ParamError(getTableName(), "mysql error by selecting", ex.displayText().data())); for (auto it = fieldNames.begin(); it != fieldNames.end(); it++) { addError(new ParamError(getTableName(), "field name for select: ", it->data())); } //addError(new ParamError(getTableName(), "field name for select: ", fieldName.data())); unlock(); } return resultCount; } template size_t ModelBase::updateIntoDB(const std::string& fieldName, const T& fieldValue) { auto cm = ConnectionManager::getInstance(); auto session = cm->getConnection(CONNECTION_MYSQL_LOGIN_SERVER); Poco::Data::Statement update(session); if (mID == 0) { addError(new Error("ModelBase::updateIntoDB", "id is zero")); return 0; } update << "UPDATE " << getTableName() << " SET " << fieldName << " = ? where id = ?", Poco::Data::Keywords::useRef(fieldValue), Poco::Data::Keywords::use(mID); size_t resultCount = 0; try { resultCount = update.execute(); } catch (Poco::Exception& ex) { lock(); addError(new ParamError(getTableName(), "mysql error by update", ex.displayText().data())); addError(new ParamError(getTableName(), "field name for update: ", fieldName.data())); unlock(); } return resultCount; } // ******************** Generic Tasks ************************************ class ModelInsertTask : public UniLib::controller::CPUTask { public: ModelInsertTask(Poco::AutoPtr model, bool loadId, bool emailErrors = false); int run(); const char* getResourceType() const { return "ModelInsertTask"; }; protected: Poco::AutoPtr mModel; bool mEmailErrors; bool mLoadId; }; template class ModelUpdateTask : public UniLib::controller::CPUTask { public: ModelUpdateTask(Poco::AutoPtr model, const std::string& fieldName, const T& fieldValue, bool emailErrors = false) : UniLib::controller::CPUTask(ServerConfig::g_CPUScheduler), mModel(model), mFieldName(fieldName), mFieldValue(fieldValue), mEmailErrors(emailErrors) { #ifdef _UNI_LIB_DEBUG setName(model->getTableName()); #endif } int run() { auto result = mModel->updateIntoDB(mFieldName, mFieldValue); if (mModel->errorCount() > 0 && mEmailErrors) { mModel->sendErrorsAsEmail(); } return !(result > 0); } const char* getResourceType() const { return "ModelUpdateTask"; }; protected: Poco::AutoPtr mModel; std::string mFieldName; T mFieldValue; bool mEmailErrors; }; } } #endif //GRADIDO_LOGIN_SERVER_MODEL_INTERFACE_INCLUDE