Add the MysqlResultImpl class

This commit is contained in:
antao 2018-11-28 15:03:31 +08:00
parent d92ce4cf9f
commit 7c907de7a6
4 changed files with 119 additions and 15 deletions

View File

@ -12,6 +12,7 @@
*/
#include "MysqlConnection.h"
#include "MysqlResultImpl.h"
#include <drogon/utils/Utilities.h>
#include <regex>
#include <algorithm>
@ -23,9 +24,11 @@ namespace drogon
namespace orm
{
Result makeResult(const std::shared_ptr<MYSQL_RES> &r = std::shared_ptr<MYSQL_RES>(nullptr), const std::string &query = "")
Result makeResult(const std::shared_ptr<MYSQL_RES> &r = std::shared_ptr<MYSQL_RES>(nullptr),
const std::string &query = "",
Result::size_type affectedRows = 0)
{
return Result(std::shared_ptr<MysqlResultImpl>(new MysqlResultImpl(r, query)));
return Result(std::shared_ptr<MysqlResultImpl>(new MysqlResultImpl(r, query, affectedRows)));
}
} // namespace orm
@ -225,7 +228,7 @@ void MysqlConnection::handleEvent()
case ExecStatus_SendQuery:
{
int err;
_waitStatus = mysql_send_query_cont(&err, _stmtPtr.get(), status);
_waitStatus = mysql_send_query_cont(&err, _mysqlPtr.get(), status);
if (_waitStatus == 0)
{
if (err)
@ -237,7 +240,7 @@ void MysqlConnection::handleEvent()
}
_execStatus = ExecStatus_StoreResult;
MYSQL_RES *ret;
_waitStatus = mysql_store_result_start(&ret, MYSQL * mysql);
_waitStatus = mysql_store_result_start(&ret, _mysqlPtr.get());
LOG_TRACE
<< "send_query completely!";
@ -248,10 +251,10 @@ void MysqlConnection::handleEvent()
case ExecStatus_StoreResult:
{
MYSQL_RES *ret;
_waitStatus = mysql_store_result_cont(&ret, MYSQL * mysql);
_waitStatus = mysql_store_result_cont(&ret, _mysqlPtr.get(), status);
if (_waitStatus == 0)
{
if(!ret)
if (!ret)
{
_execStatus = ExecStatus_None;
outputError();
@ -262,12 +265,12 @@ void MysqlConnection::handleEvent()
auto resultPtr = std::shared_ptr<MYSQL_RES>(ret, [](MYSQL_RES *r) {
mysql_free_result(r);
});
auto Result = makeResult(r, _sql);
if(_isWorking)
auto Result = makeResult(resultPtr, _sql, mysql_affected_rows(_mysqlPtr.get()));
if (_isWorking)
{
_cb(Result);
_cb = decltype(_cb)();
_exceptCb = decltype(_exceptCallback)();
_exceptCb = decltype(_exceptCb)();
_isWorking = false;
_idleCb();
_idleCb = decltype(_idleCb)();
@ -310,7 +313,7 @@ void MysqlConnection::execSql(const std::string &sql,
_loop->runInLoop([=]() {
int err;
//int mysql_send_query_start(int *ret, MYSQL *mysql, const char *q, unsigned long length)
_waitStatus = mysql_send_query_start(&err, _stmtPtr.get(), sql.c_str(), sql.length());
_waitStatus = mysql_send_query_start(&err, _mysqlPtr.get(), sql.c_str(), sql.length());
if (_waitStatus == 0)
{
if (err)

View File

@ -59,7 +59,8 @@ class MysqlConnection : public DbConnection, public std::enable_shared_from_this
{
ExecStatus_None = 0,
ExecStatus_SendQuery,
ExecStatus_StmtPrepare
ExecStatus_StmtPrepare,
ExecStatus_StoreResult
};
ExecStatus _execStatus = ExecStatus_None;
std::shared_ptr<MYSQL_STMT> _stmtPtr;

View File

@ -0,0 +1,67 @@
/**
*
* MysqlResultImpl.cc
* An Tao
*
* Copyright 2018, An Tao. All rights reserved.
* Use of this source code is governed by a MIT license
* that can be found in the License file.
*
*
*/
#include "MysqlResultImpl.h"
#include <assert.h>
#include <algorithm>
using namespace drogon::orm;
Result::size_type MysqlResultImpl::size() const noexcept
{
return _rowsNum;
}
Result::row_size_type MysqlResultImpl::columns() const noexcept
{
return _fieldNum;
}
const char *MysqlResultImpl::columnName(row_size_type number) const
{
assert(number < _fieldNum);
if (_fieldArray)
return _fieldArray[number].name;
return "";
}
Result::size_type MysqlResultImpl::affectedRows() const noexcept
{
return _affectedRows;
}
Result::row_size_type MysqlResultImpl::columnNumber(const char colName[]) const
{
if (!_fieldMapPtr)
return -1;
std::string col(colName);
std::transform(col.begin(), col.end(), col.begin(), tolower);
if (_fieldMapPtr->find(col) != _fieldMapPtr->end())
return (*_fieldMapPtr)[col];
return -1;
}
const char *MysqlResultImpl::getValue(size_type row, row_size_type column) const
{
if (_rowsNum == 0 || _fieldNum == 0)
return NULL;
assert(row < _rowsNum);
assert(column < _fieldNum);
return (*_rowsPtr)[row].first[column];
}
bool MysqlResultImpl::isNull(size_type row, row_size_type column) const
{
return getValue(row, column) == NULL;
}
Result::field_size_type MysqlResultImpl::getLength(size_type row, row_size_type column) const
{
if (_rowsNum == 0 || _fieldNum == 0)
return 0;
assert(row < _rowsNum);
assert(column < _fieldNum);
return (*_rowsPtr)[row].second[column];
}

View File

@ -16,6 +16,9 @@
#include <mysql.h>
#include <memory>
#include <string>
#include <unordered_map>
#include <algorithm>
#include <vector>
namespace drogon
{
@ -25,10 +28,34 @@ namespace orm
class MysqlResultImpl : public ResultImpl
{
public:
MysqlResultImpl(const std::shared_ptr<MYSQL_RES> &r, const std::string &query) noexcept
MysqlResultImpl(const std::shared_ptr<MYSQL_RES> &r, const std::string &query, size_type affectedRows) noexcept
: _result(r),
_query(query)
_query(query),
_rowsNum(_result ? mysql_num_rows(_result.get()) : 0),
_fieldArray(r ? mysql_fetch_fields(r.get()) : nullptr),
_fieldNum(r ? mysql_num_rows(r.get()) : 0),
_affectedRows(affectedRows)
{
if (_fieldNum > 0)
{
_fieldMapPtr = std::make_shared<std::unordered_map<std::string, row_size_type>>();
for (row_size_type i = 0; i < _fieldNum; i++)
{
std::string fieldName = _fieldArray[i].name;
std::transform(fieldName.begin(), fieldName.end(), fieldName.begin(), tolower);
(*_fieldMapPtr)[fieldName] = i;
}
}
if (size() > 0)
{
_rowsPtr = std::make_shared<std::vector<std::pair<char **, field_size_type *>>>();
MYSQL_ROW row;
while ((row = mysql_fetch_row(r.get())) != NULL)
{
auto lengths = mysql_fetch_lengths(r.get());
_rowsPtr->push_back(std::make_pair(row, lengths));
}
}
}
virtual size_type size() const noexcept override;
virtual row_size_type columns() const noexcept override;
@ -40,8 +67,14 @@ class MysqlResultImpl : public ResultImpl
virtual field_size_type getLength(size_type row, row_size_type column) const override;
private:
std::shared_ptr<MYSQL_RES> _result;
std::string _query;
const std::shared_ptr<MYSQL_RES> _result;
const std::string _query;
const Result::size_type _rowsNum;
const MYSQL_FIELD *_fieldArray;
const Result::row_size_type _fieldNum;
const size_type _affectedRows;
std::shared_ptr<std::unordered_map<std::string, row_size_type>> _fieldMapPtr;
std::shared_ptr<std::vector<std::pair<char **, field_size_type *>>> _rowsPtr;
};
} // namespace orm