integrate own mysql table format into poco data format, adding binary field value

This commit is contained in:
Dario 2019-09-28 12:14:29 +02:00
parent bb4159c701
commit cf0e70ae07
8 changed files with 106 additions and 361 deletions

View File

@ -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)

View File

@ -1,6 +1,6 @@
#include "MysqlTable.h"
#include "Poco/Mutex.h"
#include <time.h>
#include <mutex>
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>(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<unsigned char>({ '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;
}

View File

@ -13,13 +13,10 @@
#include <list>
#include <string.h>
#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<std::list<MysqlTableCell*>*> mRows;
std::string mTableName;
};

View File

@ -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;
}

View File

@ -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 <string.h>
#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

View File

@ -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:

View File

@ -1,16 +1,43 @@
#include "WriteIntoDBTask.h"
WriteIntoDBTask::WriteIntoDBTask()
WriteIntoDBTask::WriteIntoDBTask(ConnectionType type, std::vector<MysqlTable*> 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;
}

View File

@ -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<MysqlTable*> 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<MysqlTable*> mDataToInsert;
};