Skip to content

Commit 7db43b2

Browse files
committed
middle-pgsql: use std::string for prepared queries
Also makes them private and adds some more access functions instead. Fixes #731.
1 parent cf9a7e1 commit 7db43b2

File tree

2 files changed

+80
-79
lines changed

2 files changed

+80
-79
lines changed

middle-pgsql.cpp

Lines changed: 65 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -63,24 +63,22 @@ using namespace std;
6363
*
6464
* This is used for constructing SQL queries with proper tablespace settings.
6565
*/
66-
static void set_prefix_and_tbls(options_t const *options, char const **string)
66+
static void set_prefix_and_tbls(options_t const *options, std::string *string)
6767
{
68-
char buffer[1024];
69-
const char *source;
70-
char *dest;
71-
char *openbrace = nullptr;
72-
int copied = 0;
73-
74-
if (*string == nullptr) {
68+
if (string->empty()) {
7569
return;
7670
}
77-
source = *string;
78-
dest = buffer;
71+
72+
char buffer[1024];
73+
char *openbrace = nullptr;
74+
bool copied = false;
75+
char const *source = string->c_str();
76+
char *dest = buffer;
7977

8078
while (*source) {
8179
if (*source == '{') {
8280
openbrace = dest;
83-
copied = 0;
81+
copied = false;
8482
source++;
8583
continue;
8684
} else if (*source == '}') {
@@ -93,31 +91,31 @@ static void set_prefix_and_tbls(options_t const *options, char const **string)
9391
if (!options->prefix.empty()) {
9492
strcpy(dest, options->prefix.c_str());
9593
dest += strlen(options->prefix.c_str());
96-
copied = 1;
94+
copied = true;
9795
}
9896
source += 2;
9997
continue;
10098
} else if (*(source + 1) == 't') {
10199
if (options->tblsslim_data) {
102100
strcpy(dest, options->tblsslim_data->c_str());
103101
dest += strlen(options->tblsslim_data->c_str());
104-
copied = 1;
102+
copied = true;
105103
}
106104
source += 2;
107105
continue;
108106
} else if (*(source + 1) == 'i') {
109107
if (options->tblsslim_index) {
110108
strcpy(dest, options->tblsslim_index->c_str());
111109
dest += strlen(options->tblsslim_index->c_str());
112-
copied = 1;
110+
copied = true;
113111
}
114112
source += 2;
115113
continue;
116114
} else if (*(source + 1) == 'm') {
117115
if (options->unlogged) {
118116
strcpy(dest, "UNLOGGED");
119117
dest += 8;
120-
copied = 1;
118+
copied = true;
121119
}
122120
source += 2;
123121
continue;
@@ -126,27 +124,28 @@ static void set_prefix_and_tbls(options_t const *options, char const **string)
126124
*(dest++) = *(source++);
127125
}
128126
*dest = 0;
129-
*string = strdup(buffer);
127+
128+
string->assign(buffer);
130129
}
131130

132-
middle_pgsql_t::table_desc::table_desc(const char *name_, const char *create_,
133-
const char *prepare_,
134-
const char *prepare_intarray_,
135-
const char *array_indexes_)
136-
: name(name_), create(create_), prepare(prepare_),
137-
prepare_intarray(prepare_intarray_), array_indexes(array_indexes_),
138-
copyMode(0), sql_conn(nullptr), transactionMode(0)
131+
middle_pgsql_t::table_desc::table_desc(char const *name, char const *create,
132+
char const *prepare,
133+
char const *prepare_intarray,
134+
char const *array_indexes)
135+
: copyMode(0), sql_conn(nullptr), transactionMode(0), m_name(name),
136+
m_create(create), m_prepare(prepare), m_prepare_intarray(prepare_intarray),
137+
m_array_indexes(array_indexes)
139138
{}
140139

141140
void middle_pgsql_t::table_desc::connect(options_t const *options)
142141
{
143-
set_prefix_and_tbls(options, &name);
144-
set_prefix_and_tbls(options, &create);
145-
set_prefix_and_tbls(options, &prepare);
146-
set_prefix_and_tbls(options, &prepare_intarray);
147-
set_prefix_and_tbls(options, &array_indexes);
142+
set_prefix_and_tbls(options, &m_name);
143+
set_prefix_and_tbls(options, &m_create);
144+
set_prefix_and_tbls(options, &m_prepare);
145+
set_prefix_and_tbls(options, &m_prepare_intarray);
146+
set_prefix_and_tbls(options, &m_array_indexes);
148147

149-
fprintf(stderr, "Setting up table: %s\n", name);
148+
fprintf(stderr, "Setting up table: %s\n", name());
150149
sql_conn = PQconnectdb(options->database_options.conninfo().c_str());
151150

152151
// Check to see that the backend connection was successfully made, and if not, exit */
@@ -172,12 +171,30 @@ void middle_pgsql_t::table_desc::connect(options_t const *options)
172171
* This parameter does not effect safety from data corruption on the back-end.
173172
*/
174173
pgsql_exec(sql_conn, PGRES_COMMAND_OK, "SET synchronous_commit TO off;");
174+
}
175+
176+
void middle_pgsql_t::table_desc::prepare_queries(bool append)
177+
{
178+
if (!m_prepare.empty()) {
179+
pgsql_exec(sql_conn, PGRES_COMMAND_OK, "%s", m_prepare.c_str());
180+
}
181+
182+
if (append && !m_prepare_intarray.empty()) {
183+
pgsql_exec(sql_conn, PGRES_COMMAND_OK, "%s",
184+
m_prepare_intarray.c_str());
185+
}
186+
}
187+
188+
void middle_pgsql_t::table_desc::create()
189+
{
175190
pgsql_exec(sql_conn, PGRES_COMMAND_OK, "SET client_min_messages = WARNING");
191+
pgsql_exec(sql_conn, PGRES_COMMAND_OK, "%s", m_create.c_str());
192+
pgsql_exec(sql_conn, PGRES_COMMAND_OK, "RESET client_min_messages");
176193
}
177194

178195
void middle_pgsql_t::table_desc::begin_copy()
179196
{
180-
pgsql_exec(sql_conn, PGRES_COPY_IN, "COPY %s FROM STDIN", name);
197+
pgsql_exec(sql_conn, PGRES_COPY_IN, "COPY %s FROM STDIN", name());
181198
copyMode = 1;
182199
}
183200

@@ -187,14 +204,14 @@ void middle_pgsql_t::table_desc::end_copy()
187204
if (copyMode) {
188205
int stop = PQputCopyEnd(sql_conn, nullptr);
189206
if (stop != 1) {
190-
fprintf(stderr, "COPY_END for %s failed: %s\n", name,
207+
fprintf(stderr, "COPY_END for %s failed: %s\n", name(),
191208
PQerrorMessage(sql_conn));
192209
util::exit_nicely();
193210
}
194211

195212
pg_result_t res(PQgetResult(sql_conn));
196213
if (PQresultStatus(res.get()) != PGRES_COMMAND_OK) {
197-
fprintf(stderr, "COPY_END for %s failed: %s\n", name,
214+
fprintf(stderr, "COPY_END for %s failed: %s\n", name(),
198215
PQerrorMessage(sql_conn));
199216
util::exit_nicely();
200217
}
@@ -206,23 +223,23 @@ void middle_pgsql_t::table_desc::stop(bool droptemp, bool build_indexes)
206223
{
207224
time_t start, end;
208225

209-
fprintf(stderr, "Stopping table: %s\n", name);
226+
fprintf(stderr, "Stopping table: %s\n", name());
210227

211228
end_copy();
212229

213230
time(&start);
214231
if (droptemp) {
215-
pgsql_exec(sql_conn, PGRES_COMMAND_OK, "DROP TABLE %s", name);
216-
} else if (build_indexes && array_indexes) {
217-
fprintf(stderr, "Building index on table: %s\n", name);
218-
pgsql_exec(sql_conn, PGRES_COMMAND_OK, "%s", array_indexes);
232+
pgsql_exec(sql_conn, PGRES_COMMAND_OK, "DROP TABLE %s", name());
233+
} else if (build_indexes && !m_array_indexes.empty()) {
234+
fprintf(stderr, "Building index on table: %s\n", name());
235+
pgsql_exec(sql_conn, PGRES_COMMAND_OK, "%s", m_array_indexes.c_str());
219236
}
220237

221238
PQfinish(sql_conn);
222239
sql_conn = nullptr;
223240
time(&end);
224241

225-
fprintf(stderr, "Stopped table: %s in %is\n", name, (int)(end - start));
242+
fprintf(stderr, "Stopped table: %s in %is\n", name(), (int)(end - start));
226243
}
227244

228245
void middle_pgsql_t::table_desc::begin()
@@ -978,8 +995,8 @@ idlist_t middle_pgsql_t::relations_using_way(osmid_t way_id) const
978995

979996
void middle_pgsql_t::analyze()
980997
{
981-
for (auto &table : tables) {
982-
pgsql_exec(table.sql_conn, PGRES_COMMAND_OK, "ANALYZE %s", table.name);
998+
for (auto &t : tables) {
999+
pgsql_exec(t.sql_conn, PGRES_COMMAND_OK, "ANALYZE %s", t.name());
9831000
}
9841001
}
9851002

@@ -998,7 +1015,7 @@ void middle_pgsql_t::start(const options_t *out_options_)
9981015
// and pass that via the constructor to middle_t, so that middle_t
9991016
// itself doesn't need to know about details of the output.
10001017
if (out_options->output_backend == "gazetteer") {
1001-
tables[WAY_TABLE].array_indexes = nullptr;
1018+
tables[WAY_TABLE].clear_array_indexes();
10021019
mark_pending = false;
10031020
}
10041021

@@ -1019,24 +1036,15 @@ void middle_pgsql_t::start(const options_t *out_options_)
10191036
PGconn* sql_conn = table.sql_conn;
10201037

10211038
if (dropcreate) {
1022-
pgsql_exec(sql_conn, PGRES_COMMAND_OK, "DROP TABLE IF EXISTS %s CASCADE", table.name);
1039+
pgsql_exec(sql_conn, PGRES_COMMAND_OK,
1040+
"DROP TABLE IF EXISTS %s CASCADE", table.name());
10231041
}
10241042

10251043
table.begin();
1026-
1027-
if (dropcreate && table.create) {
1028-
pgsql_exec(sql_conn, PGRES_COMMAND_OK, "%s", table.create);
1029-
}
1030-
pgsql_exec(sql_conn, PGRES_COMMAND_OK, "RESET client_min_messages");
1031-
1032-
if (table.prepare) {
1033-
pgsql_exec(sql_conn, PGRES_COMMAND_OK, "%s", table.prepare);
1034-
}
1035-
1036-
if (append && table.prepare_intarray) {
1037-
pgsql_exec(sql_conn, PGRES_COMMAND_OK, "%s", table.prepare_intarray);
1044+
if (dropcreate) {
1045+
table.create();
10381046
}
1039-
1047+
table.prepare_queries(append);
10401048
table.begin_copy();
10411049
}
10421050
}
@@ -1086,8 +1094,7 @@ middle_pgsql_t::middle_pgsql_t()
10861094
/*create*/ "CREATE %m TABLE %p_nodes (id " POSTGRES_OSMID_TYPE " PRIMARY KEY {USING INDEX TABLESPACE %i}, lat int4 not null, lon int4 not null) {TABLESPACE %t};\n",
10871095
/*prepare*/ "PREPARE insert_node (" POSTGRES_OSMID_TYPE ", int4, int4) AS INSERT INTO %p_nodes VALUES ($1,$2,$3);\n"
10881096
"PREPARE get_node_list(" POSTGRES_OSMID_TYPE "[]) AS SELECT id, lat, lon FROM %p_nodes WHERE id = ANY($1::" POSTGRES_OSMID_TYPE "[]);\n"
1089-
"PREPARE delete_node (" POSTGRES_OSMID_TYPE ") AS DELETE FROM %p_nodes WHERE id = $1;\n",
1090-
/*prepare_intarray*/ nullptr
1097+
"PREPARE delete_node (" POSTGRES_OSMID_TYPE ") AS DELETE FROM %p_nodes WHERE id = $1;\n"
10911098
);
10921099
tables[WAY_TABLE] = table_desc(
10931100
/*table t_way,*/
@@ -1141,17 +1148,7 @@ middle_pgsql_t::get_query_instance(std::shared_ptr<middle_t> const &from) const
11411148
// We use a connection per table to enable the use of COPY
11421149
for (int i = 0; i < NUM_TABLES; i++) {
11431150
mid->tables[i].connect(mid->out_options);
1144-
PGconn* sql_conn = mid->tables[i].sql_conn;
1145-
1146-
if (mid->tables[i].prepare) {
1147-
pgsql_exec(sql_conn, PGRES_COMMAND_OK, "%s",
1148-
mid->tables[i].prepare);
1149-
}
1150-
1151-
if (mid->append && mid->tables[i].prepare_intarray) {
1152-
pgsql_exec(sql_conn, PGRES_COMMAND_OK, "%s",
1153-
mid->tables[i].prepare_intarray);
1154-
}
1151+
mid->tables[i].prepare_queries(mid->append);
11551152
}
11561153

11571154
return std::shared_ptr<middle_query_t>(mid.release());

middle-pgsql.hpp

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -50,34 +50,38 @@ struct middle_pgsql_t : public slim_middle_t {
5050

5151
idlist_t relations_using_way(osmid_t way_id) const override;
5252

53-
struct table_desc
53+
class table_desc
5454
{
55-
table_desc(const char *name_ = NULL,
56-
const char *create_ = NULL,
57-
const char *prepare_ = NULL,
58-
const char *prepare_intarray_ = NULL,
59-
const char *array_indexes_ = NULL);
55+
public:
56+
table_desc() : sql_conn(nullptr) {}
57+
table_desc(char const *name, char const *create,
58+
char const *prepare = "", char const *prepare_intarray = "",
59+
char const *array_indexes = "");
6060

6161
~table_desc();
6262

63-
const char *name;
64-
const char *create;
65-
const char *prepare;
66-
const char *prepare_intarray;
67-
const char *array_indexes;
63+
char const *name() const { return m_name.c_str(); }
64+
void clear_array_indexes() { m_array_indexes.clear(); }
6865

6966
int copyMode; /* True if we are in copy mode */
7067
struct pg_conn *sql_conn;
7168

7269
void connect(options_t const *options);
7370
void begin();
71+
void prepare_queries(bool append);
72+
void create();
7473
void begin_copy();
7574
void end_copy();
7675
void stop(bool droptemp, bool build_indexes);
7776
void commit();
7877

7978
private:
8079
int transactionMode; /* True if we are in an extended transaction */
80+
std::string m_name;
81+
std::string m_create;
82+
std::string m_prepare;
83+
std::string m_prepare_intarray;
84+
std::string m_array_indexes;
8185
};
8286

8387
std::shared_ptr<middle_query_t>

0 commit comments

Comments
 (0)