Skip to content

Commit 6ed7282

Browse files
committed
mapping. Introduce ResultMapper.
1 parent bd86ab6 commit 6ed7282

File tree

7 files changed

+269
-133
lines changed

7 files changed

+269
-133
lines changed

src/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ add_library(${OATPP_THIS_MODULE_NAME}
1313
oatpp-postgresql/mapping/Serializer.cpp
1414
oatpp-postgresql/mapping/Serializer.hpp
1515
oatpp-postgresql/mapping/TypeMapper.cpp
16-
oatpp-postgresql/mapping/TypeMapper.hpp oatpp-postgresql/mapping/Oid.hpp oatpp-postgresql/QueryResult.cpp oatpp-postgresql/QueryResult.hpp)
16+
oatpp-postgresql/mapping/TypeMapper.hpp oatpp-postgresql/mapping/Oid.hpp oatpp-postgresql/QueryResult.cpp oatpp-postgresql/QueryResult.hpp oatpp-postgresql/mapping/ResultMapper.cpp oatpp-postgresql/mapping/ResultMapper.hpp)
1717

1818
set_target_properties(${OATPP_THIS_MODULE_NAME} PROPERTIES
1919
CXX_STANDARD 11

src/oatpp-postgresql/Executor.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ std::shared_ptr<QueryResult> Executor::prepareQuery(const StringTemplate& queryT
6565
queryTemplate.getTemplateVariables().size(),
6666
extra->paramTypes.get());
6767

68-
auto res = std::make_shared<QueryResult>(qres, connection);
68+
auto res = std::make_shared<QueryResult>(qres, connection, m_resultMapper);
6969

7070
auto status = PQresultStatus(qres);
7171
if (status != PGRES_COMMAND_OK) {
@@ -116,7 +116,7 @@ std::shared_ptr<QueryResult> Executor::executeQuery(const StringTemplate& queryT
116116
paramFormats.get(),
117117
1);
118118

119-
auto res = std::make_shared<QueryResult>(qres, connection);
119+
auto res = std::make_shared<QueryResult>(qres, connection, m_resultMapper);
120120

121121
auto status = PQresultStatus(qres);
122122
if (status != PGRES_TUPLES_OK) {

src/oatpp-postgresql/Executor.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030

3131
#include "mapping/Serializer.hpp"
3232
#include "mapping/TypeMapper.hpp"
33+
#include "mapping/ResultMapper.hpp"
3334

3435
#include "oatpp/orm/Executor.hpp"
3536
#include "oatpp/core/parser/Caret.hpp"
@@ -49,6 +50,7 @@ class Executor : public orm::Executor {
4950
private:
5051
mapping::TypeMapper m_typeMapper;
5152
mapping::Serializer m_serializer;
53+
std::shared_ptr<mapping::ResultMapper> m_resultMapper = std::make_shared<mapping::ResultMapper>();
5254
public:
5355

5456
StringTemplate parseQueryTemplate(const oatpp::String& name,

src/oatpp-postgresql/QueryResult.cpp

Lines changed: 7 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,13 @@
2626

2727
namespace oatpp { namespace postgresql {
2828

29-
QueryResult::QueryResult(PGresult* dbResult, const std::shared_ptr<Connection>& connection)
29+
QueryResult::QueryResult(PGresult* dbResult,
30+
const std::shared_ptr<Connection>& connection,
31+
const std::shared_ptr<mapping::ResultMapper>& resultMapper)
3032
: m_dbResult(dbResult)
3133
, m_connection(connection)
32-
, m_cursor(0)
34+
, m_resultMapper(resultMapper)
35+
, m_resultData(dbResult)
3336
{
3437
auto status = PQresultStatus(m_dbResult);
3538
switch(status) {
@@ -69,68 +72,11 @@ v_int64 QueryResult::count() {
6972
}
7073

7174
std::vector<std::vector<oatpp::Void>> QueryResult::fetchRows(v_int64 count) {
72-
73-
std::vector<std::vector<oatpp::Void>> result;
74-
75-
auto leftCount = this->count() - m_cursor;
76-
auto wantToRead = count;
77-
if(wantToRead > leftCount) {
78-
wantToRead = leftCount;
79-
}
80-
81-
auto fieldsCount = PQnfields(m_dbResult);
82-
83-
for(v_int64 i = 0; i < wantToRead; i++) {
84-
85-
std::vector<oatpp::Void> row(fieldsCount);
86-
87-
for(v_int32 fieldIndex = 0; fieldIndex < fieldsCount; fieldIndex ++) {
88-
auto oid = PQftype(m_dbResult, fieldIndex);
89-
auto size = PQfsize(m_dbResult, fieldIndex);
90-
char* data = PQgetvalue(m_dbResult, m_cursor, fieldIndex);
91-
// TODO map
92-
}
93-
94-
result.push_back(std::move(row));
95-
96-
++ m_cursor;
97-
98-
}
99-
100-
return result;
101-
75+
return {};
10276
}
10377

10478
void QueryResult::fetch(oatpp::Void& polymorph, v_int64 count) {
105-
106-
auto type = polymorph.valueType;
107-
108-
if(type->classId.id == oatpp::data::mapping::type::__class::AbstractVector::CLASS_ID.id) {
109-
fetchAsList<oatpp::AbstractVector>(polymorph, count);
110-
} else if(type->classId.id == oatpp::data::mapping::type::__class::AbstractList::CLASS_ID.id) {
111-
fetchAsList<oatpp::AbstractList>(polymorph, count);
112-
} else if(type->classId.id == oatpp::data::mapping::type::__class::AbstractUnorderedSet::CLASS_ID.id) {
113-
fetchAsList<oatpp::AbstractUnorderedSet>(polymorph, count);
114-
} else {
115-
throw std::runtime_error("[oatpp::postgresql::QueryResult::fetch()]: "
116-
"Error. Invalid result container type. "
117-
"Allowed types are oatpp::Vector, oatpp::List, oatpp::UnorderedSet");
118-
}
119-
120-
}
121-
122-
oatpp::Void QueryResult::readRow(Type* type, v_int64 rowIndex) {
123-
if(type->classId.id == oatpp::data::mapping::type::__class::AbstractVector::CLASS_ID.id) {
124-
return readRowAsList<oatpp::AbstractVector>(this, type, rowIndex);
125-
} else if(type->classId.id == oatpp::data::mapping::type::__class::AbstractList::CLASS_ID.id) {
126-
return readRowAsList<oatpp::AbstractList>(this, type, rowIndex);
127-
} else if(type->classId.id == oatpp::data::mapping::type::__class::AbstractUnorderedSet::CLASS_ID.id) {
128-
return readRowAsList<oatpp::AbstractUnorderedSet>(this, type, rowIndex);
129-
} else {
130-
throw std::runtime_error("[oatpp::postgresql::QueryResult::readRow()]: "
131-
"Error. Invalid result container type. "
132-
"Allowed types are oatpp::Vector, oatpp::List, oatpp::UnorderedSet");
133-
}
79+
polymorph = m_resultMapper->readRows(&m_resultData, polymorph.valueType, count);
13480
}
13581

13682
}}

src/oatpp-postgresql/QueryResult.hpp

Lines changed: 6 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727

2828
#include "Connection.hpp"
2929
#include "mapping/Deserializer.hpp"
30+
#include "mapping/ResultMapper.hpp"
3031
#include "oatpp/orm/QueryResult.hpp"
3132

3233
namespace oatpp { namespace postgresql {
@@ -36,84 +37,20 @@ class QueryResult : public orm::QueryResult {
3637
static constexpr v_int32 TYPE_ERROR = 0;
3738
static constexpr v_int32 TYPE_COMMAND = 1;
3839
static constexpr v_int32 TYPE_TUPLES = 2;
39-
private:
40-
typedef oatpp::data::mapping::type::Type Type;
41-
private:
42-
43-
template<class Collection>
44-
static oatpp::Void readRowAsList(QueryResult* _this, Type* type, v_int64 rowIndex) {
45-
46-
auto listWrapper = type->creator();
47-
48-
auto polymorphicDispatcher = static_cast<const typename Collection::Class::AbstractPolymorphicDispatcher*>(type->polymorphicDispatcher);
49-
const auto& list = listWrapper.template staticCast<Collection>();
50-
51-
Type* itemType = *type->params.begin();
52-
53-
auto fieldsCount = PQnfields(_this->m_dbResult);
54-
55-
for(v_int32 fieldIndex = 0; fieldIndex < fieldsCount; fieldIndex ++) {
56-
57-
mapping::Deserializer::InData inData;
58-
59-
inData.oid = PQftype(_this->m_dbResult, fieldIndex);
60-
inData.size = PQfsize(_this->m_dbResult, fieldIndex);
61-
inData.data = PQgetvalue(_this->m_dbResult, rowIndex, fieldIndex);
62-
63-
polymorphicDispatcher->addPolymorphicItem(listWrapper, _this->m_deserializer.deserialize(inData, itemType));
64-
65-
}
66-
67-
return listWrapper;
68-
69-
}
70-
71-
template<class Collection>
72-
static oatpp::Void readRowAsKeyValue(QueryResult* _this, Type* type, v_int64 rowIndex) {
73-
return nullptr;
74-
}
75-
76-
oatpp::Void readRow(Type* type, v_int64 rowIndex);
77-
78-
private:
79-
80-
template<class Collection>
81-
void fetchAsList(oatpp::Void& polymorph, v_int64 count) {
82-
83-
auto type = polymorph.valueType;
84-
85-
auto listWrapper = type->creator();
86-
polymorph = listWrapper;
87-
88-
auto polymorphicDispatcher = static_cast<const typename Collection::Class::AbstractPolymorphicDispatcher*>(type->polymorphicDispatcher);
89-
const auto& list = listWrapper.template staticCast<Collection>();
90-
91-
Type* itemType = *type->params.begin();
92-
93-
auto leftCount = this->count() - m_cursor;
94-
auto wantToRead = count;
95-
if(wantToRead > leftCount) {
96-
wantToRead = leftCount;
97-
}
98-
99-
for(v_int64 i = 0; i < wantToRead; i++) {
100-
polymorphicDispatcher->addPolymorphicItem(listWrapper, readRow(itemType, m_cursor));
101-
++ m_cursor;
102-
}
103-
104-
}
105-
10640
private:
10741
PGresult* m_dbResult;
10842
std::shared_ptr<Connection> m_connection;
109-
v_int64 m_cursor;
43+
std::shared_ptr<mapping::ResultMapper> m_resultMapper;
44+
mapping::ResultMapper::ResultData m_resultData;
11045
bool m_success;
11146
v_int32 m_type;
11247
private:
11348
mapping::Deserializer m_deserializer;
11449
public:
11550

116-
QueryResult(PGresult* dbResult, const std::shared_ptr<Connection>& connection);
51+
QueryResult(PGresult* dbResult,
52+
const std::shared_ptr<Connection>& connection,
53+
const std::shared_ptr<mapping::ResultMapper>& resultMapper);
11754

11855
~QueryResult();
11956

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
/***************************************************************************
2+
*
3+
* Project _____ __ ____ _ _
4+
* ( _ ) /__\ (_ _)_| |_ _| |_
5+
* )(_)( /(__)\ )( (_ _)(_ _)
6+
* (_____)(__)(__)(__) |_| |_|
7+
*
8+
*
9+
* Copyright 2018-present, Leonid Stryzhevskyi <lganzzzo@gmail.com>
10+
*
11+
* Licensed under the Apache License, Version 2.0 (the "License");
12+
* you may not use this file except in compliance with the License.
13+
* You may obtain a copy of the License at
14+
*
15+
* http://www.apache.org/licenses/LICENSE-2.0
16+
*
17+
* Unless required by applicable law or agreed to in writing, software
18+
* distributed under the License is distributed on an "AS IS" BASIS,
19+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20+
* See the License for the specific language governing permissions and
21+
* limitations under the License.
22+
*
23+
***************************************************************************/
24+
25+
#include "ResultMapper.hpp"
26+
27+
namespace oatpp { namespace postgresql { namespace mapping {
28+
29+
ResultMapper::ResultData::ResultData(PGresult* pDbResult)
30+
: dbResult(pDbResult)
31+
{
32+
33+
rowIndex = 0;
34+
rowCount = PQntuples(dbResult);
35+
36+
{
37+
colCount = PQnfields(dbResult);
38+
for (v_int32 i = 0; i < colCount; i++) {
39+
oatpp::String colName = (const char*) PQfname(dbResult, i);
40+
colNames.push_back(colName);
41+
colIndices.insert({colName, i});
42+
}
43+
}
44+
45+
}
46+
47+
ResultMapper::ResultMapper() {
48+
49+
{
50+
m_readOneRowMethods.resize(data::mapping::type::ClassId::getClassCount(), nullptr);
51+
52+
setReadOneRowMethod(data::mapping::type::__class::AbstractObject::CLASS_ID, nullptr);
53+
54+
setReadOneRowMethod(data::mapping::type::__class::AbstractVector::CLASS_ID, &ResultMapper::readRowAsList<oatpp::AbstractVector>);
55+
setReadOneRowMethod(data::mapping::type::__class::AbstractList::CLASS_ID, &ResultMapper::readRowAsList<oatpp::AbstractList>);
56+
setReadOneRowMethod(data::mapping::type::__class::AbstractUnorderedSet::CLASS_ID, &ResultMapper::readRowAsList<oatpp::AbstractUnorderedSet>);
57+
58+
setReadOneRowMethod(data::mapping::type::__class::AbstractPairList::CLASS_ID, nullptr);
59+
setReadOneRowMethod(data::mapping::type::__class::AbstractUnorderedMap::CLASS_ID, nullptr);
60+
}
61+
62+
{
63+
m_readRowsMethods.resize(data::mapping::type::ClassId::getClassCount(), nullptr);
64+
65+
setReadRowsMethod(data::mapping::type::__class::AbstractVector::CLASS_ID, &ResultMapper::readRowsAsList<oatpp::AbstractVector>);
66+
setReadRowsMethod(data::mapping::type::__class::AbstractList::CLASS_ID, &ResultMapper::readRowsAsList<oatpp::AbstractList>);
67+
setReadRowsMethod(data::mapping::type::__class::AbstractUnorderedSet::CLASS_ID, &ResultMapper::readRowsAsList<oatpp::AbstractUnorderedSet>);
68+
69+
}
70+
71+
}
72+
73+
void ResultMapper::setReadOneRowMethod(const data::mapping::type::ClassId& classId, ReadOneRowMethod method) {
74+
const v_uint32 id = classId.id;
75+
if(id < m_readOneRowMethods.size()) {
76+
m_readOneRowMethods[id] = method;
77+
} else {
78+
throw std::runtime_error("[oatpp::postgresql::mapping::ResultMapper::setReadOneRowMethod()]: Error. Unknown classId");
79+
}
80+
}
81+
82+
void ResultMapper::setReadRowsMethod(const data::mapping::type::ClassId& classId, ReadRowsMethod method) {
83+
const v_uint32 id = classId.id;
84+
if(id < m_readRowsMethods.size()) {
85+
m_readRowsMethods[id] = method;
86+
} else {
87+
throw std::runtime_error("[oatpp::postgresql::mapping::ResultMapper::setReadRowsMethod()]: Error. Unknown classId");
88+
}
89+
}
90+
91+
oatpp::Void ResultMapper::readOneRow(ResultData* dbData, const Type* type, v_int64 rowIndex) {
92+
93+
auto id = type->classId.id;
94+
auto& method = m_readOneRowMethods[id];
95+
96+
if(method) {
97+
return (*method)(this, dbData, type, rowIndex);
98+
}
99+
100+
throw std::runtime_error("[oatpp::postgresql::mapping::ResultMapper::readOneRow()]: "
101+
"Error. Invalid result container type. "
102+
"Allowed types are oatpp::Vector, oatpp::List, oatpp::UnorderedSet");
103+
104+
}
105+
106+
oatpp::Void ResultMapper::readRows(ResultData* dbData, const Type* type, v_int64 count) {
107+
108+
auto id = type->classId.id;
109+
auto& method = m_readRowsMethods[id];
110+
111+
if(method) {
112+
return (*method)(this, dbData, type, count);
113+
}
114+
115+
throw std::runtime_error("[oatpp::postgresql::mapping::ResultMapper::readRows()]: "
116+
"Error. Invalid result container type. "
117+
"Allowed types are oatpp::Vector, oatpp::List, oatpp::UnorderedSet");
118+
119+
}
120+
121+
}}}

0 commit comments

Comments
 (0)