diff --git a/CMakeLists.txt b/CMakeLists.txt index eb8552e1b..2d221d71a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,7 +20,7 @@ FILE(GLOB SINGLETON_MANAGER "src/cpp/SingletonManager/*.h" "src/cpp/SingletonMan FILE(GLOB MODEL "src/cpp/model/*.h" "src/cpp/model/*.cpp") FILE(GLOB CRYPTO "src/cpp/Crypto/*.h" "src/cpp/Crypto/*.cpp") FILE(GLOB MAIN "src/cpp/*.cpp" "src/cpp/*.c" "src/cpp/*.h") -FILE(GLOB MYSQL "src/cpp/MySQL/*.cpp" "src/cpp/MySQL/Poco/*.h") +FILE(GLOB MYSQL "src/cpp/MySQL/*.cpp" "src/cpp/MySQL/*.h" "src/cpp/MySQL/Poco/*.h") SET(LOCAL_SRCS ${TINF} ${MAIN} ${HTTPInterface} ${CRYPTO} ${MODEL} ${SINGLETON_MANAGER} ${MYSQL} ${TASKS}) aux_source_directory("src/cpp" LOCAL_SRCS) diff --git a/src/cpp/MySQL/MysqlTable.cpp b/src/cpp/MySQL/MysqlTable.cpp index e55c458e7..4fd9290d6 100644 --- a/src/cpp/MySQL/MysqlTable.cpp +++ b/src/cpp/MySQL/MysqlTable.cpp @@ -1,6 +1,6 @@ #include "MysqlTable.h" +#include "Poco/Mutex.h" #include -#include MysqlTable::MysqlTable(size_t fieldCount) : mFieldCount(fieldCount), mHeader(nullptr) @@ -68,6 +68,34 @@ bool MysqlTable::addCellToCurrentRow(MysqlTableCell* cell) return true; } +//using namespace Poco::Data::Keywords +// new Binding(t, name, AbstractBinding::PD_IN); +int MysqlTable::connectToStatement(Poco::Data::Statement* stmt, int rowIndex/* = 0*/) +{ + std::string strCopy; + for (auto itRow = mRows.begin(); itRow != mRows.end(); itRow++) { + if (0 == rowIndex) { + for (auto itCell = (*itRow)->begin(); itCell != (*itRow)->end(); itCell++) { + switch ((*itCell)->getType()) { + case MYSQL_ROW_STRING: + strCopy = (const char*)(*itCell); + stmt->bind(strCopy); + break; + case MYSQL_ROW_INT: stmt->bind((long)(*itCell)); break; + case MYSQL_ROW_LONG: stmt->bind((long long)(*itCell)); break; + case MYSQL_ROW_BINARY: + // Poco::Data::BLOB data(std::vector({ '0', '0', '0', '0', '0', '0', '0', '0', '0', '0' })); + Poco::Data::BLOB data((unsigned char*)(*itCell), (*itCell)->size()); + stmt->bind(data); + break; + } + } + break; + } + rowIndex--; + } + return 0; +} size_t MysqlTable::getFieldTypeSize(MysqlRowType type) { @@ -80,104 +108,12 @@ size_t MysqlTable::getFieldTypeSize(MysqlRowType type) return 0; } -bool MysqlTable::addCellToCurrentRow(MYSQL_BIND* bind) -{ - if (!bind) { - addError(new Error(__FUNCTION__, "bind is null")); - return false; - } - /* - SQL Type of Received Value buffer_type Value Output Variable C Type - TINYINT MYSQL_TYPE_TINY signed char - SMALLINT MYSQL_TYPE_SHORT short int - MEDIUMINT MYSQL_TYPE_INT24 int - INT MYSQL_TYPE_LONG int - BIGINT MYSQL_TYPE_LONGLONG long long int - FLOAT MYSQL_TYPE_FLOAT float - DOUBLE MYSQL_TYPE_DOUBLE double - DECIMAL MYSQL_TYPE_NEWDECIMAL char[] - YEAR MYSQL_TYPE_SHORT short int - TIME MYSQL_TYPE_TIME MYSQL_TIME - DATE MYSQL_TYPE_DATE MYSQL_TIME - DATETIME MYSQL_TYPE_DATETIME MYSQL_TIME - TIMESTAMP MYSQL_TYPE_TIMESTAMP MYSQL_TIME - CHAR, BINARY MYSQL_TYPE_STRING char[] - VARCHAR, VARBINARY MYSQL_TYPE_VAR_STRING char[] - TINYBLOB, TINYTEXT MYSQL_TYPE_TINY_BLOB char[] - BLOB, TEXT MYSQL_TYPE_BLOB char[] - MEDIUMBLOB, MEDIUMTEXT MYSQL_TYPE_MEDIUM_BLOB char[] - LONGBLOB, LONGTEXT MYSQL_TYPE_LONG_BLOB char[] - BIT MYSQL_TYPE_BIT char[] - */ - signed char* b = nullptr; - short* s = nullptr; - int* i = nullptr; - long long* ll = nullptr; - float* f = nullptr; - double* d = nullptr; - char* c_str = nullptr; - MYSQL_TIME* time = nullptr; - - switch (bind->buffer_type) { - case MYSQL_TYPE_TINY: - b = (signed char*)bind->buffer; - addCellToCurrentRow((long)b[0]); - break; - case MYSQL_TYPE_SHORT: - s = (short*)bind->buffer; - addCellToCurrentRow((long)s[0]); - break; - case MYSQL_TYPE_INT24: - case MYSQL_TYPE_LONG: - i = (int*)bind->buffer; - addCellToCurrentRow((long)i[0]); - break; - case MYSQL_TYPE_LONGLONG: - ll = (long long*)bind->buffer; - addCellToCurrentRow(ll[0]); - break; - case MYSQL_TYPE_FLOAT: - f = (float*)bind->buffer; - addCellToCurrentRow((double)f[0]); - break; - case MYSQL_TYPE_DOUBLE: - d = (double*)bind->buffer; - addCellToCurrentRow(d[0]); - break; - case MYSQL_TYPE_NEWDECIMAL: - case MYSQL_TYPE_STRING: - case MYSQL_TYPE_VAR_STRING: - case MYSQL_TYPE_TINY_BLOB: - case MYSQL_TYPE_BLOB: - case MYSQL_TYPE_MEDIUM_BLOB: - case MYSQL_TYPE_LONG_BLOB: - case MYSQL_TYPE_BIT: - c_str = (char*)bind->buffer; - addCellToCurrentRow(new MysqlTableCellString(c_str, bind->buffer_length)); - break; - case MYSQL_TYPE_TIME: - case MYSQL_TYPE_DATE: - case MYSQL_TYPE_DATETIME: - case MYSQL_TYPE_TIMESTAMP: - time = (MYSQL_TIME*)bind->buffer; - addCellToCurrentRow(new MysqlTableCellDateTime(time[0])); - break; - default: - addError(new ParamError(__FUNCTION__, "unhandled mysql buffer type", bind->buffer_type)); - return false; - } - - return true; - -} - - time_t MysqlTable::parseFromMysqlDateTime(const char* mysql_date_time) { struct tm * parsedTime; // used because localtime return an internal pointer, not thread safe - static std::mutex timeMutex; + static Poco::Mutex timeMutex; int year, month, day, hour, minute, second; // ex: 2009-10-29 @@ -205,43 +141,3 @@ time_t MysqlTable::parseFromMysqlDateTime(const char* mysql_date_time) } return 0; } - -bool MysqlTable::writeAsTableOntoLuaStack(lua_State* l) -{ - /* - * http://lua-users.org/wiki/SimpleLuaApiExample - * Ok, now here we go: We pass data to the lua script on the stack. - * That is, we first have to prepare Lua's virtual stack the way we - * want the script to receive it, then ask Lua to run it. - */ - lua_newtable(l); /* We will pass a table */ - - /* - * To put values into the table, we first push the index, then the - * value, and then call lua_rawset() with the index of the table in the - * stack. Let's see why it's -3: In Lua, the value -1 always refers to - * the top of the stack. When you create the table with lua_newtable(), - * the table gets pushed into the top of the stack. When you push the - * index and then the cell value, the stack looks like: - * - * <- [stack bottom] -- table, index, value [top] - * - * So the -1 will refer to the cell value, thus -3 is used to refer to - * the table itself. Note that lua_rawset() pops the two last elements - * of the stack, so that after it has been called, the table is at the - * top of the stack. - */ - - /* - * for (i = 1; i <= 5; i++) { - * lua_pushnumber(L, i); // Push the table index - * lua_pushnumber(L, i * 2); // Push the cell value - * lua_rawset(L, -3); // Stores the pair in the table - *} - */ - for (auto it = mRows.begin(); it != mRows.end(); it++) { - - } - return false; - -} \ No newline at end of file diff --git a/src/cpp/MySQL/MysqlTable.h b/src/cpp/MySQL/MysqlTable.h index e7dc3cdf8..113a1603f 100644 --- a/src/cpp/MySQL/MysqlTable.h +++ b/src/cpp/MySQL/MysqlTable.h @@ -13,13 +13,10 @@ #include #include -#include "../Error/ErrorList.h" +#include "../model/ErrorList.h" #include "mysql.h" -extern "C" { -#include "../import/lua/luaintf.h" -#include "../import/lua/lauxlib.h" -} +#include "Poco/Data/Session.h" enum MysqlRowType { @@ -29,6 +26,7 @@ enum MysqlRowType { MYSQL_ROW_DECIMAL, // double MYSQL_ROW_TIMESTAMP, MYSQL_ROW_DATETIME, + MYSQL_ROW_BINARY, MYSQL_ROW_NULL, MYSQL_ROW_TYPE_COUNT, MYSQL_ROW_TYPE_NONE @@ -53,11 +51,14 @@ public: inline bool isDateTime() const { return mType == MYSQL_ROW_DATETIME; } inline bool isNull() const { return mType == MYSQL_ROW_NULL; } inline bool isDecimal() const { return mType == MYSQL_ROW_DECIMAL; } + inline bool isBinary() const { return mType == MYSQL_ROW_BINARY; } inline MysqlRowType getType() const { return mType; } virtual operator const char*() const { return ""; } virtual operator long() const { return 0; } virtual operator long long() const { return 0; } + virtual operator unsigned char*() const { return nullptr; } + virtual size_t size() { return 0; } protected: MysqlRowType mType; @@ -71,6 +72,7 @@ public: virtual operator const char*() const { return mContent.data(); } + virtual size_t size() { return mContent.size(); } protected: std::string mContent; }; @@ -123,6 +125,26 @@ protected: double mDecimal; }; +class MysqlTableCellBinary : public MysqlTableCell +{ +public: + MysqlTableCellBinary(const unsigned char* data, size_t _size) :MysqlTableCell(MYSQL_ROW_BINARY), m_data(nullptr), m_size(_size) { + m_data = (unsigned char*)malloc(m_size); + memcpy(m_data, data, m_size); + } + ~MysqlTableCellBinary() { + if (m_data) free(m_data); + m_data = nullptr; + m_size = 0; + } + + virtual operator unsigned char*() const { return m_data; } + virtual size_t size() { return m_size; } +protected: + unsigned char* m_data; + size_t m_size; + +}; class MysqlTable : public ErrorList { @@ -142,9 +164,9 @@ public: inline bool addCellToCurrentRow(const long long& value) { return addCellToCurrentRow(new MysqlTableCellLong(value)); } inline bool addCellToCurrentRow(const char* string) { return addCellToCurrentRow(new MysqlTableCellString(string)); } inline bool addCellToCurrentRow(const double& value) { return addCellToCurrentRow(new MysqlTableCellDecimal(value)); } + inline bool addCellToCurrentRow(const unsigned char* bytes, size_t size) { return addCellToCurrentRow(new MysqlTableCellBinary(bytes, size)); } inline bool addCellToCurrentRowTime(const time_t& time) { return addCellToCurrentRow(new MysqlTableCellTimestamp(time)); } inline bool addCellToCurrentRow() { return addCellToCurrentRow(new MysqlTableCell); } - bool addCellToCurrentRow(MYSQL_BIND* bind); //bool copyColumnValues() @@ -157,9 +179,12 @@ public: if (fieldIndex >= mFieldCount || fieldIndex < 0) return MYSQL_ROW_TYPE_NONE; return mHeader[fieldIndex].type; } - /// move to ParseMysqlTable - bool writeAsTableOntoLuaStack(lua_State* l); + inline void setTableName(const char* tableName) { mTableName = tableName; } + inline const char* getTableName() { return mTableName.data(); } + + int connectToStatement(Poco::Data::Statement* stmt, int rowIndex = 0); + static size_t getFieldTypeSize(MysqlRowType type); static time_t parseFromMysqlDateTime(const char* mysql_date_time); @@ -168,6 +193,7 @@ protected: size_t mFieldCount; MysqlTableColumn* mHeader; std::list*> mRows; + std::string mTableName; }; diff --git a/src/cpp/MySQL/MysqlTableArray.cpp b/src/cpp/MySQL/MysqlTableArray.cpp deleted file mode 100644 index fdce33d1d..000000000 --- a/src/cpp/MySQL/MysqlTableArray.cpp +++ /dev/null @@ -1,97 +0,0 @@ -#include "MysqlTableArray.h" - -MysqlTableArray::MysqlTableArray(size_t fieldCount, size_t rowCount) - : mFieldCount(fieldCount), mRowCount(rowCount), mHeader(nullptr), mDataBuffer(nullptr) -{ - if (fieldCount < 150) { - mHeader = new MysqlTableColumn[fieldCount]; - mDataBuffer = (void**)malloc(sizeof(void*) * fieldCount); - memset(mDataBuffer, 0, sizeof(void*) * fieldCount); - } - else { - addError(new Error(__FUNCTION__, "field count greater than 150")); - } -} - -MysqlTableArray::~MysqlTableArray() -{ - for (int i = 0; i < mFieldCount; i++) { - if (mHeader[i].type == MYSQL_ROW_STRING) { - std::string* strArray = (std::string*)mDataBuffer[i]; - delete[] strArray; - } - else { - free(mDataBuffer[i]); - } - } - free(mDataBuffer); - mDataBuffer = nullptr; - delete[] mHeader; - mHeader = nullptr; -} - -bool MysqlTableArray::setHeader(int index, const char* name, MysqlRowType type) -{ - if (index < 0 || index >= mFieldCount) { - return false; - } - if (!mHeader) { - return false; - } - - mHeader[index].name = name; - mHeader[index].type = type; - - auto fieldSize = MysqlTable::getFieldTypeSize(type); - if (MYSQL_ROW_STRING == type) { - if (mDataBuffer[index]) delete[] mDataBuffer[index]; - mDataBuffer[index] = new std::string[mRowCount]; - } - else if (fieldSize) { - if (mDataBuffer[index]) free(mDataBuffer[index]); - mDataBuffer[index] = malloc(fieldSize * mRowCount); - memset(mDataBuffer[index], 0, fieldSize * mRowCount); - } - else { - addError(new ParamError(__FUNCTION__, "wrong type for MysqlTableArray: ", type)); - return false; - } - - return true; -} - -MysqlRowType MysqlTableArray::getRowType(int index) -{ - if (index < 0 || index >= mFieldCount) { - addError(new ParamError(__FUNCTION__, "invalid index:", index)); - return MYSQL_ROW_TYPE_NONE; - } - if (!mHeader) { - addError(new Error(__FUNCTION__, "error, header not allocated")); - return MYSQL_ROW_TYPE_NONE; - } - return mHeader[index].type; -} - -bool MysqlTableArray::checkIndexValid(int fieldIndex, int rowIndex, MysqlRowType type) -{ - if (fieldIndex < 0 || fieldIndex >= mFieldCount) { - addError(new ParamError(__FUNCTION__, "error fieldIndex invalid:", fieldIndex)); - return false; - } - if (rowIndex < 0 || rowIndex >= mRowCount) { - addError(new ParamError(__FUNCTION__, "error rowIndex invalid:", rowIndex)); - return false; - } - if (!mHeader || mHeader[fieldIndex].type != type) { - addError(new ParamError(__FUNCTION__, "error wrong type:", type)); - return false; - } - if (!mDataBuffer[fieldIndex]) { - addError(new Error(__FUNCTION__, "no memory allocated")); - return false; - } - - return true; - -} \ No newline at end of file diff --git a/src/cpp/MySQL/MysqlTableArray.h b/src/cpp/MySQL/MysqlTableArray.h deleted file mode 100644 index a47b0ad15..000000000 --- a/src/cpp/MySQL/MysqlTableArray.h +++ /dev/null @@ -1,114 +0,0 @@ - -/*! -* -* \author: einhornimmond -* -* \date: 11.05.19 -* -* \brief: mysql Table as array prepared for prepared statement (cache optimized) -*/ - -#ifndef DR_LUA_WEB_MODULE_STRUCTURES_MYSQL_MYSQL_TABLE_ARRAY__H -#define DR_LUA_WEB_MODULE_STRUCTURES_MYSQL_MYSQL_TABLE_ARRAY__H - -#include -#include "../Error/ErrorList.h" -#include "MysqlTable.h" - -extern "C" { -#include "../import/lua/luaintf.h" -#include "../import/lua/lauxlib.h" -} - - -class MysqlTableArray : public ErrorList -{ -public: - MysqlTableArray(size_t fieldCount, size_t rowCount); - ~MysqlTableArray(); - - bool setHeader(int index, const char* name, MysqlRowType type); - MysqlRowType getRowType(int index); - - inline size_t getRowCount() const { return mRowCount; } - inline size_t getFieldCount() const { return mFieldCount; } - inline MysqlRowType getRowType(int fieldIndex) const { - if (fieldIndex >= mFieldCount || fieldIndex < 0) return MYSQL_ROW_TYPE_NONE; - return mHeader[fieldIndex].type; - } - - inline bool setFieldValue(int fieldIndex, int rowIndex, const long& value) { - if (checkIndexValid(fieldIndex, rowIndex, MYSQL_ROW_INT)) { - auto dataArray = (long*)mDataBuffer[fieldIndex]; - dataArray[rowIndex] = value; - return true; - } - return false; - } - inline bool setFieldValue(int fieldIndex, int rowIndex, const long long& value) { - if (checkIndexValid(fieldIndex, rowIndex, MYSQL_ROW_LONG)) { - auto dataArray = (long long*)mDataBuffer[fieldIndex]; - dataArray[rowIndex] = value; - return true; - } - return false; - } - inline bool setFieldValue(int fieldIndex, int rowIndex, const char* value) { - if (checkIndexValid(fieldIndex, rowIndex, MYSQL_ROW_STRING)) { - auto dataArray = (std::string*)mDataBuffer[fieldIndex]; - dataArray[rowIndex] = value; - return true; - } - return false; - } - inline bool setFieldValue(int fieldIndex, int rowIndex, const double& value) { - if (checkIndexValid(fieldIndex, rowIndex, MYSQL_ROW_DECIMAL)) { - auto dataArray = (double*)mDataBuffer[fieldIndex]; - dataArray[rowIndex] = value; - return true; - } - return false; - } - - inline long* getIntRow(int fieldIndex) { - if (fieldIndex < 0 || fieldIndex >= mFieldCount || mHeader[fieldIndex].type != MYSQL_ROW_INT) { - addError(new ParamError(__FUNCTION__, "invalid field index", fieldIndex)); - return nullptr; - } - return (long*)mDataBuffer[fieldIndex]; - } - inline long long* getLongRow(int fieldIndex) { - if (fieldIndex < 0 || fieldIndex >= mFieldCount || mHeader[fieldIndex].type != MYSQL_ROW_LONG) { - addError(new ParamError(__FUNCTION__, "invalid field index", fieldIndex)); - return nullptr; - } - return (long long*)mDataBuffer[fieldIndex]; - } - inline std::string* getStringRow(int fieldIndex) { - if (fieldIndex < 0 || fieldIndex >= mFieldCount || mHeader[fieldIndex].type != MYSQL_ROW_STRING) { - addError(new ParamError(__FUNCTION__, "invalid field index", fieldIndex)); - return nullptr; - } - return (std::string*)mDataBuffer[fieldIndex]; - } - - inline double* getDecimalRow(int fieldIndex) { - if (fieldIndex < 0 || fieldIndex >= mFieldCount || mHeader[fieldIndex].type != MYSQL_ROW_DECIMAL) { - addError(new ParamError(__FUNCTION__, "invalid field index", fieldIndex)); - return nullptr; - } - return (double*)mDataBuffer[fieldIndex]; - } - - -protected: - bool checkIndexValid(int fieldIndex, int rowIndex, MysqlRowType type); - - size_t mFieldCount; - size_t mRowCount; - MysqlTableColumn* mHeader; - void** mDataBuffer; -}; - - -#endif //DR_LUA_WEB_MODULE_STRUCTURES_MYSQL_MYSQL_TABLE_ARRAY__H \ No newline at end of file diff --git a/src/cpp/SingletonManager/ConnectionManager.h b/src/cpp/SingletonManager/ConnectionManager.h index 93dfdf359..e62ce8e46 100644 --- a/src/cpp/SingletonManager/ConnectionManager.h +++ b/src/cpp/SingletonManager/ConnectionManager.h @@ -7,6 +7,7 @@ #include "Poco/Util/LayeredConfiguration.h" #include "Poco/Data/SessionPoolContainer.h" #include "Poco/Data/MySQL/Connector.h" +#include "Poco/Exception.h" #include "../Model/ErrorList.h" @@ -37,13 +38,15 @@ public: inline Poco::Data::Session getConnection(ConnectionType type) { switch (type) { - case CONNECTION_MYSQL_LOGIN_SERVER: - break; + case CONNECTION_MYSQL_LOGIN_SERVER: case CONNECTION_MYSQL_PHP_SERVER: - break; + return mSessionPools.get(mSessionPoolNames[type]); default: + addError(new ParamError("[ConnectionManager::getConnection]", "Connection Type unknown", std::to_string(type))); break; } + throw Poco::NotFoundException("Connection Type unknown", std::to_string(type)); + //return Poco::Data::Session(nullptr); } protected: diff --git a/src/cpp/tasks/WriteIntoDBTask.cpp b/src/cpp/tasks/WriteIntoDBTask.cpp index 62a13595d..b8d6e5d20 100644 --- a/src/cpp/tasks/WriteIntoDBTask.cpp +++ b/src/cpp/tasks/WriteIntoDBTask.cpp @@ -1,16 +1,43 @@ #include "WriteIntoDBTask.h" -WriteIntoDBTask::WriteIntoDBTask() +WriteIntoDBTask::WriteIntoDBTask(ConnectionType type, std::vector multipleData) + : mFinished(false), mConnectionType(type), mDataToInsert(multipleData) { } WriteIntoDBTask::~WriteIntoDBTask() { - + for (auto it = mDataToInsert.begin(); it != mDataToInsert.end(); it++) { + delete *it; + } + mDataToInsert.clear(); } int WriteIntoDBTask::run() { + auto cm = ConnectionManager::getInstance(); + auto session = cm->getConnection(mConnectionType); + + for (auto it = mDataToInsert.begin(); it != mDataToInsert.end(); it++) { + auto tableName = (*it)->getTableName(); + Poco::Data::Statement insert(session); + /*insert << "INSERT INTO Person VALUES(?, ?, ?)", + use(person.name), + use(person.address), + use(person.age);*/ + insert << "INSERT INTO " << tableName << "VALUES("; + for (int iCell = 0; iCell < (*it)->getFieldCount(); iCell++) { + if (iCell > 0) insert << ","; + insert << "?"; + } + insert << ")"; + (*it)->connectToStatement(&insert); + insert.execute(); + } + lock(); + mFinished = true; + unlock(); + return 0; } \ No newline at end of file diff --git a/src/cpp/tasks/WriteIntoDBTask.h b/src/cpp/tasks/WriteIntoDBTask.h index e0f1dc1a1..e220d3e0b 100644 --- a/src/cpp/tasks/WriteIntoDBTask.h +++ b/src/cpp/tasks/WriteIntoDBTask.h @@ -3,23 +3,27 @@ #include "Task.h" #include "../SingletonManager/ConnectionManager.h" +#include "../MySQL/MysqlTable.h" #include "Poco/Tuple.h" class WriteIntoDBTask : public UniLib::controller::Task { public: - WriteIntoDBTask(ConnectionType type, std::vector<); + //! \param multipleData clear table in deconstruction, call delete for every entry + WriteIntoDBTask(ConnectionType type, std::vector multipleData); virtual ~WriteIntoDBTask(); virtual int run(); virtual const char* getResourceType() const { return "WriteIntoDBTask"; }; + virtual bool isTaskFinished() { return true; } protected: private: + bool mFinished; ConnectionType mConnectionType; - + std::vector mDataToInsert; };