Skip to content

Commit bd86ab6

Browse files
committed
Fetch results POC.
1 parent 2cab4d7 commit bd86ab6

File tree

11 files changed

+463
-55
lines changed

11 files changed

+463
-55
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)
16+
oatpp-postgresql/mapping/TypeMapper.hpp oatpp-postgresql/mapping/Oid.hpp oatpp-postgresql/QueryResult.cpp oatpp-postgresql/QueryResult.hpp)
1717

1818
set_target_properties(${OATPP_THIS_MODULE_NAME} PROPERTIES
1919
CXX_STANDARD 11

src/oatpp-postgresql/Connection.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,14 +25,14 @@
2525
#ifndef oatpp_postgresql_Connection_hpp
2626
#define oatpp_postgresql_Connection_hpp
2727

28-
#include "oatpp/database/Connection.hpp"
28+
#include "oatpp/orm/Connection.hpp"
2929
#include "oatpp/core/Types.hpp"
3030

3131
#include <libpq-fe.h>
3232

3333
namespace oatpp { namespace postgresql {
3434

35-
class Connection : public database::Connection {
35+
class Connection : public orm::Connection {
3636
private:
3737
PGconn* m_connection;
3838
std::unordered_set<oatpp::String> m_prepared;

src/oatpp-postgresql/Executor.cpp

Lines changed: 47 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@
2626

2727
#include "ql_template/Parser.hpp"
2828
#include "ql_template/TemplateValueProvider.hpp"
29+
30+
#include "QueryResult.hpp"
31+
2932
#include "oatpp/core/data/stream/ChunkedBuffer.hpp"
3033

3134
#include <vector>
@@ -50,8 +53,8 @@ std::unique_ptr<Oid[]> Executor::getParamTypes(const StringTemplate& queryTempla
5053

5154
}
5255

53-
void Executor::prepareQuery(const StringTemplate& queryTemplate,
54-
const std::shared_ptr<postgresql::Connection>& connection)
56+
std::shared_ptr<QueryResult> Executor::prepareQuery(const StringTemplate& queryTemplate,
57+
const std::shared_ptr<postgresql::Connection>& connection)
5558
{
5659

5760
auto extra = std::static_pointer_cast<ql_template::Parser::TemplateExtra>(queryTemplate.getExtraData());
@@ -62,18 +65,22 @@ void Executor::prepareQuery(const StringTemplate& queryTemplate,
6265
queryTemplate.getTemplateVariables().size(),
6366
extra->paramTypes.get());
6467

68+
auto res = std::make_shared<QueryResult>(qres, connection);
69+
6570
auto status = PQresultStatus(qres);
6671
if (status != PGRES_COMMAND_OK) {
6772
OATPP_LOGD("Executor::prepareQuery", "execute prepare failed: %s", PQerrorMessage(connection->getHandle()));
6873
} else {
6974
OATPP_LOGD("Executor::prepareQuery", "OK");
7075
}
7176

77+
return res;
78+
7279
}
7380

74-
void Executor::executeQuery(const StringTemplate& queryTemplate,
75-
const std::unordered_map<oatpp::String, oatpp::Void>& params,
76-
const std::shared_ptr<postgresql::Connection>& connection)
81+
std::shared_ptr<QueryResult> Executor::executeQuery(const StringTemplate& queryTemplate,
82+
const std::unordered_map<oatpp::String, oatpp::Void>& params,
83+
const std::shared_ptr<postgresql::Connection>& connection)
7784
{
7885

7986
auto extra = std::static_pointer_cast<ql_template::Parser::TemplateExtra>(queryTemplate.getExtraData());
@@ -107,15 +114,44 @@ void Executor::executeQuery(const StringTemplate& queryTemplate,
107114
paramValues.get(),
108115
paramLengths.get(),
109116
paramFormats.get(),
110-
0);
117+
1);
118+
119+
auto res = std::make_shared<QueryResult>(qres, connection);
111120

112121
auto status = PQresultStatus(qres);
113122
if (status != PGRES_TUPLES_OK) {
114123
OATPP_LOGD("Database", "execute query failed: %s", PQerrorMessage(connection->getHandle()));
115124
} else {
116125
OATPP_LOGD("Database", "OK_2");
126+
127+
auto fieldsCount = PQnfields(qres);
128+
data::stream::ChunkedBuffer stream;
129+
130+
for(v_int32 i = 0; i < fieldsCount; i++) {
131+
stream << oatpp::String(PQfname(qres, i)) << " | ";
132+
}
133+
134+
stream << "\n---------------\n";
135+
136+
auto rows = PQntuples(qres);
137+
for(v_int32 i = 0; i < rows; i++) {
138+
stream << "[";
139+
for(v_int32 fieldIndex = 0; fieldIndex < fieldsCount; fieldIndex ++) {
140+
auto oid = PQftype(qres, fieldIndex);
141+
auto size = PQfsize(qres, fieldIndex);
142+
stream << "{oid=" << oid << ", size=" << size << ", val=" << /**((p_int64) */(const char*)PQgetvalue(qres, i, fieldIndex) << "}, ";
143+
}
144+
stream << "]\n";
145+
}
146+
147+
auto text = stream.toString();
148+
149+
OATPP_LOGD("RES", "%s", text->c_str());
150+
117151
}
118152

153+
return res;
154+
119155
}
120156

121157
data::share::StringTemplate Executor::parseQueryTemplate(const oatpp::String& name,
@@ -139,7 +175,7 @@ data::share::StringTemplate Executor::parseQueryTemplate(const oatpp::String& na
139175

140176
}
141177

142-
std::shared_ptr<database::Connection> Executor::getConnection() {
178+
std::shared_ptr<orm::Connection> Executor::getConnection() {
143179

144180
oatpp::String dbHost = "localhost";
145181
oatpp::String dbUser = "postgres";
@@ -162,9 +198,9 @@ std::shared_ptr<database::Connection> Executor::getConnection() {
162198

163199
}
164200

165-
database::QueryResult Executor::execute(const StringTemplate& queryTemplate,
166-
const std::unordered_map<oatpp::String, oatpp::Void>& params,
167-
const std::shared_ptr<database::Connection>& connection)
201+
std::shared_ptr<orm::QueryResult> Executor::execute(const StringTemplate& queryTemplate,
202+
const std::unordered_map<oatpp::String, oatpp::Void>& params,
203+
const std::shared_ptr<orm::Connection>& connection)
168204
{
169205

170206
auto pgConnection = std::static_pointer_cast<postgresql::Connection>(connection);
@@ -183,9 +219,8 @@ database::QueryResult Executor::execute(const StringTemplate& queryTemplate,
183219
}
184220

185221
OATPP_LOGD("AAA", "query={%s}", res->c_str());
186-
executeQuery(queryTemplate, params, pgConnection);
187222

188-
return database::QueryResult();
223+
return executeQuery(queryTemplate, params, pgConnection);
189224

190225
}
191226

src/oatpp-postgresql/Executor.hpp

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -26,22 +26,26 @@
2626
#define oatpp_postgresql_Executor_hpp
2727

2828
#include "Connection.hpp"
29+
#include "QueryResult.hpp"
2930

3031
#include "mapping/Serializer.hpp"
3132
#include "mapping/TypeMapper.hpp"
3233

33-
#include "oatpp/database/Executor.hpp"
34+
#include "oatpp/orm/Executor.hpp"
3435
#include "oatpp/core/parser/Caret.hpp"
3536

3637
namespace oatpp { namespace postgresql {
3738

38-
class Executor : public database::Executor {
39+
class Executor : public orm::Executor {
3940
private:
4041
std::unique_ptr<Oid[]> getParamTypes(const StringTemplate& queryTemplate, const ParamsTypeMap& paramsTypeMap);
41-
void prepareQuery(const StringTemplate& queryTemplate, const std::shared_ptr<postgresql::Connection>& connection);
42-
void executeQuery(const StringTemplate& queryTemplate,
43-
const std::unordered_map<oatpp::String, oatpp::Void>& params,
44-
const std::shared_ptr<postgresql::Connection>& connection);
42+
43+
std::shared_ptr<QueryResult> prepareQuery(const StringTemplate& queryTemplate,
44+
const std::shared_ptr<postgresql::Connection>& connection);
45+
46+
std::shared_ptr<QueryResult> executeQuery(const StringTemplate& queryTemplate,
47+
const std::unordered_map<oatpp::String, oatpp::Void>& params,
48+
const std::shared_ptr<postgresql::Connection>& connection);
4549
private:
4650
mapping::TypeMapper m_typeMapper;
4751
mapping::Serializer m_serializer;
@@ -51,11 +55,11 @@ class Executor : public database::Executor {
5155
const oatpp::String& text,
5256
const ParamsTypeMap& paramsTypeMap) override;
5357

54-
std::shared_ptr<database::Connection> getConnection() override;
58+
std::shared_ptr<orm::Connection> getConnection() override;
5559

56-
database::QueryResult execute(const StringTemplate& queryTemplate,
57-
const std::unordered_map<oatpp::String, oatpp::Void>& params,
58-
const std::shared_ptr<database::Connection>& connection) override;
60+
std::shared_ptr<orm::QueryResult> execute(const StringTemplate& queryTemplate,
61+
const std::unordered_map<oatpp::String, oatpp::Void>& params,
62+
const std::shared_ptr<orm::Connection>& connection) override;
5963

6064
};
6165

src/oatpp-postgresql/QueryResult.cpp

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
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 "QueryResult.hpp"
26+
27+
namespace oatpp { namespace postgresql {
28+
29+
QueryResult::QueryResult(PGresult* dbResult, const std::shared_ptr<Connection>& connection)
30+
: m_dbResult(dbResult)
31+
, m_connection(connection)
32+
, m_cursor(0)
33+
{
34+
auto status = PQresultStatus(m_dbResult);
35+
switch(status) {
36+
case PGRES_TUPLES_OK: {
37+
m_success = true;
38+
m_type = TYPE_TUPLES;
39+
break;
40+
}
41+
42+
case PGRES_COMMAND_OK: {
43+
m_success = true;
44+
m_type = TYPE_COMMAND;
45+
break;
46+
}
47+
48+
default: {
49+
m_success = false;
50+
m_type = TYPE_ERROR;
51+
}
52+
}
53+
}
54+
55+
QueryResult::~QueryResult() {
56+
PQclear(m_dbResult);
57+
}
58+
59+
bool QueryResult::isSuccess() {
60+
return m_success;
61+
}
62+
63+
v_int64 QueryResult::count() {
64+
switch(m_type) {
65+
case TYPE_TUPLES: return PQntuples(m_dbResult);
66+
// case TYPE_COMMAND: return 0;
67+
}
68+
return 0;
69+
}
70+
71+
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+
102+
}
103+
104+
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+
}
134+
}
135+
136+
}}

0 commit comments

Comments
 (0)