Skip to content

Commit b804afe

Browse files
committed
Executor. Parameters mapping: support DTO properties traversal.
1 parent 4bd6cb9 commit b804afe

File tree

7 files changed

+137
-72
lines changed

7 files changed

+137
-72
lines changed

src/oatpp-postgresql/Executor.cpp

Lines changed: 94 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,8 @@ class VersionRow : public oatpp::DTO {
5757
Executor::QueryParams::QueryParams(const StringTemplate& queryTemplate,
5858
const std::unordered_map<oatpp::String, oatpp::Void>& params,
5959
const mapping::TypeMapper& typeMapper,
60-
const mapping::Serializer& serializer)
60+
const mapping::Serializer& serializer,
61+
const data::mapping::type::BaseObject::PropertyTraverser& objectTraverser)
6162
{
6263

6364
auto extra = std::static_pointer_cast<ql_template::Parser::TemplateExtra>(queryTemplate.getExtraData());
@@ -78,42 +79,116 @@ Executor::QueryParams::QueryParams(const StringTemplate& queryTemplate,
7879
paramFormats.resize(count);
7980

8081
for(v_uint32 i = 0; i < count; i ++) {
82+
8183
const auto& var = queryTemplate.getTemplateVariables()[i];
8284
auto it = params.find(var.name);
83-
if(it == params.end()) {
84-
throw std::runtime_error("[oatpp::postgresql::Executor::QueryParams::QueryParams()]: "
85-
"Error. Parameter not found " + var.name->std_str());
85+
86+
if(it != params.end()) {
87+
88+
auto& data = outData[i];
89+
serializer.serialize(data, it->second);
90+
91+
paramOids[i] = typeMapper.getTypeOid(it->second.valueType);
92+
paramValues[i] = data.data;
93+
paramLengths[i] = data.dataSize;
94+
paramFormats[i] = data.dataFormat;
95+
96+
continue;
97+
8698
}
8799

88-
auto& data = outData[i];
89-
serializer.serialize(data, it->second);
100+
auto dtoParam = paramNameAsDtoParam(var.name);
101+
if(dtoParam.name) {
102+
it = params.find(dtoParam.name);
103+
if(it != params.end() && it->second.valueType->classId.id == data::mapping::type::__class::AbstractObject::CLASS_ID.id) {
104+
auto value = objectTraverser.findPropertyValue(it->second, dtoParam.propertyPath, {});
105+
if(value.valueType->classId.id != oatpp::Void::Class::CLASS_ID.id) {
106+
107+
auto& data = outData[i];
108+
serializer.serialize(data, value);
109+
110+
paramOids[i] = typeMapper.getTypeOid(value.valueType);
111+
paramValues[i] = data.data;
112+
paramLengths[i] = data.dataSize;
113+
paramFormats[i] = data.dataFormat;
114+
115+
continue;
116+
117+
}
118+
}
119+
}
120+
121+
throw std::runtime_error("[oatpp::postgresql::Executor::QueryParams::QueryParams()]: "
122+
"Error. Parameter not found " + var.name->std_str());
90123

91-
paramOids[i] = typeMapper.getTypeOid(it->second.valueType);
92-
paramValues[i] = data.data;
93-
paramLengths[i] = data.dataSize;
94-
paramFormats[i] = data.dataFormat;
95124
}
96125

97126
}
98127

99128
Executor::Executor(const std::shared_ptr<provider::Provider<Connection>>& connectionProvider)
100129
: m_connectionProvider(connectionProvider)
101130
, m_resultMapper(std::make_shared<mapping::ResultMapper>())
102-
{}
131+
{
132+
m_objectTraverser.addKnownTypes({
133+
Uuid::Class::CLASS_ID
134+
});
135+
}
136+
137+
Executor::DtoParam Executor::paramNameAsDtoParam(const oatpp::String& paramName) {
138+
139+
parser::Caret caret(paramName);
140+
auto nameLabel = caret.putLabel();
141+
if(caret.findChar('.') && caret.getPosition() < caret.getDataSize() - 1) {
103142

143+
DtoParam result;
144+
result.name = nameLabel.toString();
145+
146+
do {
147+
148+
caret.inc();
149+
auto label = caret.putLabel();
150+
caret.findChar('.');
151+
result.propertyPath.push_back(label.std_str());
152+
153+
} while (caret.getPosition() < caret.getDataSize());
154+
155+
return result;
156+
157+
}
158+
159+
return {};
160+
161+
}
104162

105163
std::unique_ptr<Oid[]> Executor::getParamTypes(const StringTemplate& queryTemplate, const ParamsTypeMap& paramsTypeMap) {
106164

107165
std::unique_ptr<Oid[]> result(new Oid[queryTemplate.getTemplateVariables().size()]);
108166

109167
for(v_uint32 i = 0; i < queryTemplate.getTemplateVariables().size(); i++) {
110-
const auto& v = queryTemplate.getTemplateVariables()[i];
111-
auto it = paramsTypeMap.find(v.name);
112-
if(it == paramsTypeMap.end()) {
113-
throw std::runtime_error("[oatpp::postgresql::Executor::getParamTypes()]: Error. "
114-
"Type info not found for variable " + v.name->std_str());
168+
169+
const auto& var = queryTemplate.getTemplateVariables()[i];
170+
auto it = paramsTypeMap.find(var.name);
171+
172+
if(it != paramsTypeMap.end()) {
173+
result.get()[i] = m_typeMapper.getTypeOid(it->second);
174+
continue;
175+
}
176+
177+
auto dtoParam = paramNameAsDtoParam(var.name);
178+
if(dtoParam.name) {
179+
it = paramsTypeMap.find(dtoParam.name);
180+
if(it != paramsTypeMap.end() && it->second->classId.id == data::mapping::type::__class::AbstractObject::CLASS_ID.id) {
181+
auto type = m_objectTraverser.findPropertyType(it->second, dtoParam.propertyPath, {});
182+
if(type) {
183+
result.get()[i] = m_typeMapper.getTypeOid(type);
184+
continue;
185+
}
186+
}
115187
}
116-
result.get()[i] = m_typeMapper.getTypeOid(it->second);
188+
189+
throw std::runtime_error("[oatpp::postgresql::Executor::getParamTypes()]: Error. "
190+
"Type info not found for variable " + var.name->std_str());
191+
117192
}
118193

119194
return result;
@@ -141,7 +216,7 @@ std::shared_ptr<QueryResult> Executor::executeQueryPrepared(const StringTemplate
141216
const std::shared_ptr<postgresql::Connection>& connection)
142217
{
143218

144-
QueryParams queryParams(queryTemplate, params, m_typeMapper, m_serializer);
219+
QueryParams queryParams(queryTemplate, params, m_typeMapper, m_serializer, m_objectTraverser);
145220

146221
PGresult *qres = PQexecPrepared(connection->getHandle(),
147222
queryParams.queryName,
@@ -160,7 +235,7 @@ std::shared_ptr<QueryResult> Executor::executeQuery(const StringTemplate& queryT
160235
const std::shared_ptr<postgresql::Connection>& connection)
161236
{
162237

163-
QueryParams queryParams(queryTemplate, params, m_typeMapper, m_serializer);
238+
QueryParams queryParams(queryTemplate, params, m_typeMapper, m_serializer, m_objectTraverser);
164239

165240
PGresult *qres = PQexecParams(connection->getHandle(),
166241
queryParams.query,

src/oatpp-postgresql/Executor.hpp

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
#include "mapping/Serializer.hpp"
3232
#include "mapping/TypeMapper.hpp"
3333
#include "mapping/ResultMapper.hpp"
34+
#include "Types.hpp"
3435

3536
#include "oatpp/orm/Executor.hpp"
3637
#include "oatpp/core/parser/Caret.hpp"
@@ -40,6 +41,15 @@
4041
namespace oatpp { namespace postgresql {
4142

4243
class Executor : public orm::Executor {
44+
private:
45+
46+
struct DtoParam {
47+
oatpp::String name;
48+
std::vector<std::string> propertyPath;
49+
};
50+
51+
static DtoParam paramNameAsDtoParam(const oatpp::String& paramName);
52+
4353
private:
4454

4555
class QueryParams {
@@ -50,7 +60,8 @@ class Executor : public orm::Executor {
5060
QueryParams(const StringTemplate& queryTemplate,
5161
const std::unordered_map<oatpp::String, oatpp::Void>& params,
5262
const mapping::TypeMapper& typeMapper,
53-
const mapping::Serializer& serializer);
63+
const mapping::Serializer& serializer,
64+
const data::mapping::type::BaseObject::PropertyTraverser& objectTraverser);
5465

5566
int count;
5667

@@ -96,6 +107,7 @@ class Executor : public orm::Executor {
96107
std::shared_ptr<mapping::ResultMapper> m_resultMapper;
97108
mapping::TypeMapper m_typeMapper;
98109
mapping::Serializer m_serializer;
110+
data::mapping::type::BaseObject::PropertyTraverser m_objectTraverser;
99111
public:
100112

101113
Executor(const std::shared_ptr<provider::Provider<Connection>>& connectionProvider);

src/oatpp-postgresql/mapping/ResultMapper.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -90,8 +90,9 @@ void ResultMapper::setReadRowsMethod(const data::mapping::type::ClassId& classId
9090

9191
oatpp::Void ResultMapper::readRowAsObject(ResultMapper* _this, ResultData* dbData, const Type* type, v_int64 rowIndex) {
9292

93-
auto object = type->creator();
94-
const auto& fieldsMap = type->propertiesGetter()->getMap();
93+
auto dispatcher = static_cast<const data::mapping::type::__class::AbstractObject::PolymorphicDispatcher*>(type->polymorphicDispatcher);
94+
auto object = dispatcher->createObject();
95+
const auto& fieldsMap = dispatcher->getProperties()->getMap();
9596

9697
for(auto& f : fieldsMap) {
9798

@@ -104,7 +105,7 @@ oatpp::Void ResultMapper::readRowAsObject(ResultMapper* _this, ResultData* dbDat
104105
if(colIt != dbData->colIndices.end()) {
105106
auto i = colIt->second;
106107
mapping::Deserializer::InData inData(dbData->dbResult, rowIndex, i);
107-
field->set(object.get(), _this->m_deserializer.deserialize(inData, field->type));
108+
field->set(static_cast<oatpp::BaseObject*>(object.get()), _this->m_deserializer.deserialize(inData, field->type));
108109
}
109110

110111
}

src/oatpp-postgresql/mapping/ResultMapper.hpp

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -56,12 +56,11 @@ class ResultMapper {
5656
template<class Collection>
5757
static oatpp::Void readRowAsList(ResultMapper* _this, ResultData* dbData, const Type* type, v_int64 rowIndex) {
5858

59-
auto listWrapper = type->creator();
60-
61-
auto polymorphicDispatcher = static_cast<const typename Collection::Class::AbstractPolymorphicDispatcher*>(type->polymorphicDispatcher);
59+
auto polymorphicDispatcher = static_cast<const typename Collection::Class::PolymorphicDispatcher*>(type->polymorphicDispatcher);
60+
auto listWrapper = polymorphicDispatcher->createObject();
6261
const auto& list = listWrapper.template staticCast<Collection>();
6362

64-
Type* itemType = *type->params.begin();
63+
const Type* itemType = *type->params.begin();
6564

6665
for(v_int32 i = 0; i < dbData->colCount; i ++) {
6766
mapping::Deserializer::InData inData(dbData->dbResult, rowIndex, i);
@@ -75,17 +74,17 @@ class ResultMapper {
7574
template<class Collection>
7675
static oatpp::Void readRowAsKeyValue(ResultMapper* _this, ResultData* dbData, const Type* type, v_int64 rowIndex) {
7776

78-
auto mapWrapper = type->creator();
79-
auto polymorphicDispatcher = static_cast<const typename Collection::Class::AbstractPolymorphicDispatcher*>(type->polymorphicDispatcher);
77+
auto polymorphicDispatcher = static_cast<const typename Collection::Class::PolymorphicDispatcher*>(type->polymorphicDispatcher);
78+
auto mapWrapper = polymorphicDispatcher->createObject();
8079
const auto& map = mapWrapper.template staticCast<Collection>();
8180

8281
auto it = type->params.begin();
83-
Type* keyType = *it ++;
82+
const Type* keyType = *it ++;
8483
if(keyType->classId.id != oatpp::data::mapping::type::__class::String::CLASS_ID.id){
8584
throw std::runtime_error("[oatpp::postgresql::mapping::ResultMapper::readRowAsKeyValue()]: Invalid map key. Key should be String");
8685
}
87-
Type* valueType = *it;
8886

87+
const Type* valueType = *it;
8988
for(v_int32 i = 0; i < dbData->colCount; i ++) {
9089
mapping::Deserializer::InData inData(dbData->dbResult, rowIndex, i);
9190
polymorphicDispatcher->addPolymorphicItem(mapWrapper, dbData->colNames[i], _this->m_deserializer.deserialize(inData, valueType));
@@ -99,12 +98,11 @@ class ResultMapper {
9998
template<class Collection>
10099
static oatpp::Void readRowsAsList(ResultMapper* _this, ResultData* dbData, const Type* type, v_int64 count) {
101100

102-
auto listWrapper = type->creator();
103-
104-
auto polymorphicDispatcher = static_cast<const typename Collection::Class::AbstractPolymorphicDispatcher*>(type->polymorphicDispatcher);
101+
auto polymorphicDispatcher = static_cast<const typename Collection::Class::PolymorphicDispatcher*>(type->polymorphicDispatcher);
102+
auto listWrapper = polymorphicDispatcher->createObject();
105103
const auto& list = listWrapper.template staticCast<Collection>();
106104

107-
Type* itemType = *type->params.begin();
105+
const Type* itemType = *type->params.begin();
108106

109107
auto leftCount = dbData->rowCount - dbData->rowIndex;
110108
auto wantToRead = count;

src/oatpp-postgresql/mapping/type/Uuid.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ namespace __class {
7878

7979
oatpp::Type* Uuid::getType() {
8080
static Type type(
81-
CLASS_ID, nullptr, nullptr, nullptr, nullptr,
81+
CLASS_ID, nullptr, nullptr,
8282
{
8383
{"postgresql", new Inter()}
8484
}
Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,18 @@
11
DROP TABLE IF EXISTS test_floats;
22

33
CREATE TABLE test_floats (
4-
f_decimal decimal,
5-
f_number numeric(1000),
64
f_real real,
75
f_double double precision
86
);
97

108
INSERT INTO test_floats
11-
(f_decimal, f_number, f_real, f_double) VALUES (null, null, null, null);
9+
(f_real, f_double) VALUES (null, null);
1210

1311
INSERT INTO test_floats
14-
(f_decimal, f_number, f_real, f_double) VALUES (0, 0, 0, 0);
12+
(f_real, f_double) VALUES (0, 0);
1513

1614
INSERT INTO test_floats
17-
(f_decimal, f_number, f_real, f_double) VALUES (0.1, 0.1, 0.1, 0.1);
15+
(f_real, f_double) VALUES (1, 2);
1816

1917
INSERT INTO test_floats
20-
(f_decimal, f_number, f_real, f_double) VALUES (-0.1, -0.1, -0.1, -0.1);
21-
18+
(f_real, f_double) VALUES (-1, -2);

0 commit comments

Comments
 (0)