Skip to content

Commit e982efe

Browse files
committed
Refactor postgres into a base class too
1 parent cd36f16 commit e982efe

File tree

2 files changed

+84
-65
lines changed

2 files changed

+84
-65
lines changed

src/db-postgresql.cpp

+61-52
Original file line numberDiff line numberDiff line change
@@ -9,21 +9,75 @@
99

1010
#define ARRLEN(x) (sizeof(x) / sizeof((x)[0]))
1111

12+
/* PostgreSQLBase */
13+
14+
PostgreSQLBase::~PostgreSQLBase()
15+
{
16+
if (db)
17+
PQfinish(db);
18+
}
19+
20+
void PostgreSQLBase::openDatabase(const char *connect_string)
21+
{
22+
if (db)
23+
throw std::logic_error("Database already open");
24+
25+
db = PQconnectdb(connect_string);
26+
if (PQstatus(db) != CONNECTION_OK) {
27+
throw std::runtime_error(std::string("PostgreSQL database error: ") +
28+
PQerrorMessage(db)
29+
);
30+
}
31+
}
32+
33+
PGresult *PostgreSQLBase::checkResults(PGresult *res, bool clear)
34+
{
35+
ExecStatusType statusType = PQresultStatus(res);
36+
37+
switch (statusType) {
38+
case PGRES_COMMAND_OK:
39+
case PGRES_TUPLES_OK:
40+
break;
41+
case PGRES_FATAL_ERROR:
42+
throw std::runtime_error(
43+
std::string("PostgreSQL database error: ") +
44+
PQresultErrorMessage(res)
45+
);
46+
default:
47+
throw std::runtime_error(
48+
std::string("Unhandled PostgreSQL result code ") +
49+
std::to_string(statusType)
50+
);
51+
}
52+
53+
if (clear)
54+
PQclear(res);
55+
return res;
56+
}
57+
58+
PGresult *PostgreSQLBase::execPrepared(
59+
const char *stmtName, const int paramsNumber,
60+
const void **params,
61+
const int *paramsLengths, const int *paramsFormats,
62+
bool clear)
63+
{
64+
return checkResults(PQexecPrepared(db, stmtName, paramsNumber,
65+
(const char* const*) params, paramsLengths, paramsFormats,
66+
1 /* binary output */), clear
67+
);
68+
}
69+
70+
/* DBPostgreSQL */
71+
1272
DBPostgreSQL::DBPostgreSQL(const std::string &mapdir)
1373
{
1474
std::ifstream ifs(mapdir + "world.mt");
1575
if (!ifs.good())
1676
throw std::runtime_error("Failed to read world.mt");
1777
std::string connect_string = read_setting("pgsql_connection", ifs);
1878
ifs.close();
19-
db = PQconnectdb(connect_string.c_str());
2079

21-
if (PQstatus(db) != CONNECTION_OK) {
22-
throw std::runtime_error(std::string(
23-
"PostgreSQL database error: ") +
24-
PQerrorMessage(db)
25-
);
26-
}
80+
openDatabase(connect_string.c_str());
2781

2882
prepareStatement(
2983
"get_block_pos",
@@ -56,7 +110,6 @@ DBPostgreSQL::~DBPostgreSQL()
56110
} catch (const std::exception& caught) {
57111
std::cerr << "could not finalize: " << caught.what() << std::endl;
58112
}
59-
PQfinish(db);
60113
}
61114

62115

@@ -169,50 +222,6 @@ void DBPostgreSQL::getBlocksByPos(BlockList &blocks,
169222
}
170223
}
171224

172-
173-
PGresult *DBPostgreSQL::checkResults(PGresult *res, bool clear)
174-
{
175-
ExecStatusType statusType = PQresultStatus(res);
176-
177-
switch (statusType) {
178-
case PGRES_COMMAND_OK:
179-
case PGRES_TUPLES_OK:
180-
break;
181-
case PGRES_FATAL_ERROR:
182-
throw std::runtime_error(
183-
std::string("PostgreSQL database error: ") +
184-
PQresultErrorMessage(res)
185-
);
186-
default:
187-
throw std::runtime_error(
188-
"Unhandled PostgreSQL result code"
189-
);
190-
}
191-
192-
if (clear)
193-
PQclear(res);
194-
195-
return res;
196-
}
197-
198-
void DBPostgreSQL::prepareStatement(const std::string &name, const std::string &sql)
199-
{
200-
checkResults(PQprepare(db, name.c_str(), sql.c_str(), 0, NULL));
201-
}
202-
203-
PGresult *DBPostgreSQL::execPrepared(
204-
const char *stmtName, const int paramsNumber,
205-
const void **params,
206-
const int *paramsLengths, const int *paramsFormats,
207-
bool clear
208-
)
209-
{
210-
return checkResults(PQexecPrepared(db, stmtName, paramsNumber,
211-
(const char* const*) params, paramsLengths, paramsFormats,
212-
1 /* binary output */), clear
213-
);
214-
}
215-
216225
int DBPostgreSQL::pg_binary_to_int(PGresult *res, int row, int col)
217226
{
218227
int32_t* raw = reinterpret_cast<int32_t*>(PQgetvalue(res, row, col));

src/db-postgresql.h

+23-13
Original file line numberDiff line numberDiff line change
@@ -3,29 +3,39 @@
33
#include "db.h"
44
#include <libpq-fe.h>
55

6-
class DBPostgreSQL : public DB {
6+
class PostgreSQLBase {
77
public:
8-
DBPostgreSQL(const std::string &mapdir);
9-
std::vector<BlockPos> getBlockPosXZ(BlockPos min, BlockPos max) override;
10-
void getBlocksOnXZ(BlockList &blocks, int16_t x, int16_t z,
11-
int16_t min_y, int16_t max_y) override;
12-
void getBlocksByPos(BlockList &blocks,
13-
const std::vector<BlockPos> &positions) override;
14-
~DBPostgreSQL() override;
15-
16-
bool preferRangeQueries() const override { return true; }
8+
~PostgreSQLBase();
179

1810
protected:
11+
void openDatabase(const char *connect_string);
12+
1913
PGresult *checkResults(PGresult *res, bool clear = true);
20-
void prepareStatement(const std::string &name, const std::string &sql);
14+
void prepareStatement(const std::string &name, const std::string &sql) {
15+
checkResults(PQprepare(db, name.c_str(), sql.c_str(), 0, NULL));
16+
}
2117
PGresult *execPrepared(
2218
const char *stmtName, const int paramsNumber,
2319
const void **params,
2420
const int *paramsLengths = nullptr, const int *paramsFormats = nullptr,
2521
bool clear = true
2622
);
27-
int pg_binary_to_int(PGresult *res, int row, int col);
23+
24+
PGconn *db = NULL;
25+
};
26+
27+
class DBPostgreSQL : public DB, PostgreSQLBase {
28+
public:
29+
DBPostgreSQL(const std::string &mapdir);
30+
std::vector<BlockPos> getBlockPosXZ(BlockPos min, BlockPos max) override;
31+
void getBlocksOnXZ(BlockList &blocks, int16_t x, int16_t z,
32+
int16_t min_y, int16_t max_y) override;
33+
void getBlocksByPos(BlockList &blocks,
34+
const std::vector<BlockPos> &positions) override;
35+
~DBPostgreSQL() override;
36+
37+
bool preferRangeQueries() const override { return true; }
2838

2939
private:
30-
PGconn *db;
40+
int pg_binary_to_int(PGresult *res, int row, int col);
3141
};

0 commit comments

Comments
 (0)