1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
|
#pragma once
#include <database/statement.hpp>
#include <logger/logger.hpp>
#include <libpq-fe.h>
class PostgresqlStatement: public Statement
{
public:
PostgresqlStatement(std::string body, PGconn*const conn):
body(std::move(body)),
conn(conn)
{}
~PostgresqlStatement()
{
PQclear(this->result);
this->result = nullptr;
}
PostgresqlStatement(const PostgresqlStatement&) = delete;
PostgresqlStatement& operator=(const PostgresqlStatement&) = delete;
PostgresqlStatement(PostgresqlStatement&& other) = delete;
PostgresqlStatement& operator=(PostgresqlStatement&& other) = delete;
StepResult step() override final
{
if (!this->executed)
{
this->current_tuple = 0;
this->executed = true;
if (!this->execute())
return StepResult::Error;
}
else
{
this->current_tuple++;
}
if (this->current_tuple < PQntuples(this->result))
return StepResult::Row;
return StepResult::Done;
}
int64_t get_column_int64(const int col) override
{
const char* result = PQgetvalue(this->result, this->current_tuple, col);
std::istringstream iss;
iss.str(result);
int64_t res;
iss >> res;
return res;
}
std::string get_column_text(const int col) override
{
const char* result = PQgetvalue(this->result, this->current_tuple, col);
return result;
}
int get_column_int(const int col) override
{
const char* result = PQgetvalue(this->result, this->current_tuple, col);
std::istringstream iss;
iss.str(result);
int res;
iss >> res;
return res;
}
void bind(std::vector<std::string> params) override
{
this->params = std::move(params);
}
bool bind_text(const int, const std::string& data) override
{
this->params.push_back(data);
return true;
}
bool bind_int64(const int, const std::int64_t value) override
{
this->params.push_back(std::to_string(value));
return true;
}
bool bind_null(const int) override
{
this->params.push_back("NULL");
return true;
}
private:
private:
bool execute()
{
std::vector<const char*> params;
params.reserve(this->params.size());
for (const auto& param: this->params)
params.push_back(param.data());
const int param_size = static_cast<int>(this->params.size());
this->result = PQexecParams(this->conn, this->body.data(),
param_size,
nullptr,
params.data(),
nullptr,
nullptr,
0);
const auto status = PQresultStatus(this->result);
if (status != PGRES_TUPLES_OK && status != PGRES_COMMAND_OK)
{
log_error("Failed to execute command: ", PQresultErrorMessage(this->result));
return false;
}
return true;
}
bool executed{false};
std::string body;
PGconn*const conn;
std::vector<std::string> params;
PGresult* result{nullptr};
int current_tuple{0};
};
|