Skip to content

Commit 308933a

Browse files
committed
Introduce psql_array_ids_to_vector
1 parent c2e0270 commit 308933a

File tree

5 files changed

+194
-143
lines changed

5 files changed

+194
-143
lines changed

include/cgimap/backend/apidb/common_pgsql_selection.hpp

-4
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,5 @@ void extract_changesets(
5151
const std::chrono::system_clock::time_point &now,
5252
bool include_changeset_discussions);
5353

54-
// parses psql array based on specs given
55-
// https://www.postgresql.org/docs/current/static/arrays.html#ARRAYS-IO
56-
std::vector<std::string> psql_array_to_vector(std::string_view str);
57-
std::vector<std::string> psql_array_to_vector(const pqxx::field& field);
5854

5955
#endif /* CGIMAP_BACKEND_APIDB_COMMON_PGSQL_SELECTION_HPP */

include/cgimap/backend/apidb/utils.hpp

+11
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,15 @@
1919
*/
2020
void check_postgres_version(pqxx::connection_base &conn);
2121

22+
// parses psql array based on specs given
23+
// https://www.postgresql.org/docs/current/static/arrays.html#ARRAYS-IO
24+
std::vector<std::string> psql_array_to_vector(std::string_view str, int size_hint = 0);
25+
std::vector<std::string> psql_array_to_vector(const pqxx::field& field, int size_hint = 0);
26+
27+
template <typename T>
28+
std::vector<T> psql_array_ids_to_vector(const pqxx::field& field);
29+
30+
template <typename T>
31+
std::vector<T> psql_array_ids_to_vector(std::string_view str);
32+
2233
#endif /* CGIMAP_BACKEND_APIDB_UTILS_HPP */

src/backend/apidb/common_pgsql_selection.cpp

+32-139
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,6 @@
1212
#include "cgimap/backend/apidb/utils.hpp"
1313

1414
#include <chrono>
15-
#include <charconv>
16-
1715

1816
namespace {
1917

@@ -209,32 +207,14 @@ std::optional<T> extract_optional(const pqxx_field &f) {
209207
tags.reserve(keys.size());
210208

211209
for (std::size_t i = 0; i < keys.size(); i++)
212-
tags.emplace_back(keys[i], values[i]);
210+
tags.emplace_back(std::move(keys[i]), std::move(values[i]));
213211

214212
return tags;
215213
}
216214

217-
[[nodiscard]] nodes_t extract_nodes(const pqxx_tuple &row, const way_extra_columns& col) {
218-
219-
nodes_t nodes;
220-
221-
auto ids = psql_array_to_vector(row[col.node_ids_col]);
222-
223-
nodes.reserve(ids.size());
224-
225-
for (const auto & id : ids) {
226-
osm_nwr_id_t node{};
227-
228-
auto [_, ec] = std::from_chars(id.data(), id.data() + id.size(), node);
215+
[[nodiscard]] nodes_t extract_way_nodes(const pqxx_tuple &row, const way_extra_columns& col) {
229216

230-
if (ec != std::errc()) {
231-
throw std::runtime_error("Node id conversion to integer failed");
232-
}
233-
234-
nodes.push_back(node);
235-
}
236-
237-
return nodes;
217+
return psql_array_ids_to_vector<osm_nwr_id_t>(row[col.node_ids_col]);
238218
}
239219

240220
element_type type_from_name(const char *name) {
@@ -269,9 +249,9 @@ element_type type_from_name(const char *name) {
269249

270250
members_t members;
271251

272-
auto types = psql_array_to_vector(row[col.member_types_col]);
273-
auto ids = psql_array_to_vector(row[col.member_ids_col]);
274-
auto roles = psql_array_to_vector(row[col.member_roles_col]);
252+
auto ids = psql_array_ids_to_vector<osm_nwr_id_t>(row[col.member_ids_col]);
253+
auto types = psql_array_to_vector(row[col.member_types_col], ids.size());
254+
auto roles = psql_array_to_vector(row[col.member_roles_col], ids.size());
275255

276256
if (types.size() != ids.size() ||
277257
ids.size() != roles.size()) {
@@ -281,19 +261,8 @@ element_type type_from_name(const char *name) {
281261
members.reserve(ids.size());
282262

283263
for (std::size_t i=0; i<ids.size(); i++) {
284-
member_info member;
285-
member.type = type_from_name(types[i].c_str());
286-
287-
{
288-
auto [_, ec] = std::from_chars(ids[i].data(), ids[i].data() + ids[i].size(), member.ref);
289-
290-
if (ec != std::errc()) {
291-
throw std::runtime_error("Member ref conversion to integer failed");
292-
}
293-
}
294-
295-
member.role = roles[i];
296-
members.push_back(member);
264+
element_type member_type = type_from_name(types[i].c_str());
265+
members.emplace_back(member_type, ids[i], std::move(roles[i]));
297266
}
298267

299268
return members;
@@ -303,11 +272,11 @@ element_type type_from_name(const char *name) {
303272

304273
comments_t comments;
305274

306-
auto id = psql_array_to_vector(row[col.comment_id_col]);
307-
auto author_id = psql_array_to_vector(row[col.comment_author_id_col]);
308-
auto display_name = psql_array_to_vector(row[col.comment_display_name_col]);
309-
auto body = psql_array_to_vector(row[col.comment_body_col]);
310-
auto created_at = psql_array_to_vector(row[col.comment_created_at_col]);
275+
auto id = psql_array_ids_to_vector<osm_changeset_comment_id_t>(row[col.comment_id_col]);
276+
auto author_id = psql_array_ids_to_vector<osm_user_id_t>(row[col.comment_author_id_col]);
277+
auto display_name = psql_array_to_vector(row[col.comment_display_name_col], id.size());
278+
auto body = psql_array_to_vector(row[col.comment_body_col], id.size());
279+
auto created_at = psql_array_to_vector(row[col.comment_created_at_col], id.size());
311280

312281
if (id.size() != author_id.size() ||
313282
author_id.size() != display_name.size() ||
@@ -319,29 +288,11 @@ element_type type_from_name(const char *name) {
319288
comments.reserve(id.size());
320289

321290
for (std::size_t i=0; i<id.size(); i++) {
322-
323-
changeset_comment_info comment;
324-
325-
{
326-
auto [_, ec] = std::from_chars(id[i].data(), id[i].data() + id[i].size(), comment.id);
327-
328-
if (ec != std::errc()) {
329-
throw std::runtime_error("Comment id conversion to integer failed");
330-
}
331-
}
332-
333-
{
334-
auto [_, ec] = std::from_chars(author_id[i].data(), author_id[i].data() + author_id[i].size(), comment.author_id);
335-
336-
if (ec != std::errc()) {
337-
throw std::runtime_error("Author id conversion to integer failed");
338-
}
339-
}
340-
341-
comment.author_display_name = display_name[i];
342-
comment.body = body[i];
343-
comment.created_at = created_at[i];
344-
comments.push_back(comment);
291+
comments.emplace_back(id[i],
292+
author_id[i],
293+
std::move(body[i]),
294+
std::move(created_at[i]),
295+
std::move(display_name[i]));
345296
}
346297

347298
return comments;
@@ -352,12 +303,11 @@ struct node {
352303
using extra_columns = node_extra_columns;
353304

354305
struct extra_info {
355-
double lon;
356-
double lat;
357-
inline void extract(const pqxx_tuple &row, const extra_columns& col) {
358-
lon = double(row[col.longitude_col].as<int64_t>()) / (global_settings::get_scale());
359-
lat = double(row[col.latitude_col].as<int64_t>()) / (global_settings::get_scale());
360-
}
306+
const double lon;
307+
const double lat;
308+
extra_info(const pqxx_tuple &row, const extra_columns& col) :
309+
lon(double(row[col.longitude_col].as<int64_t>()) / global_settings::get_scale()),
310+
lat(double(row[col.latitude_col].as<int64_t>()) / global_settings::get_scale()) {}
361311
};
362312
static inline void write(
363313
output_formatter &formatter, const element_info &elem,
@@ -370,27 +320,26 @@ struct way {
370320
using extra_columns = way_extra_columns;
371321

372322
struct extra_info {
373-
nodes_t nodes;
374-
inline void extract(const pqxx_tuple &row, const extra_columns& col) {
375-
nodes = extract_nodes(row, col);
376-
}
323+
const nodes_t way_nodes;
324+
extra_info(const pqxx_tuple &row, const extra_columns& col) :
325+
way_nodes(extract_way_nodes(row, col)) {}
377326
};
378327

379328
static inline void write(
380329
output_formatter &formatter, const element_info &elem,
381330
const extra_info &extra, const tags_t &tags) {
382-
formatter.write_way(elem, extra.nodes, tags);
331+
formatter.write_way(elem, extra.way_nodes, tags);
383332
}
384333
};
385334

386335
struct relation {
387336
using extra_columns = relation_extra_columns;
388337

389338
struct extra_info {
390-
members_t members;
391-
inline void extract(const pqxx_tuple &row, const extra_columns& col) {
392-
members = extract_members(row, col);
393-
}
339+
const members_t members;
340+
extra_info(const pqxx_tuple &row, const extra_columns& col) :
341+
members(extract_members(row, col)) {}
342+
394343
};
395344

396345
static inline void write(
@@ -411,9 +360,8 @@ void extract(
411360
const tag_columns tag_cols(rows);
412361

413362
for (const auto &row : rows) {
414-
typename T::extra_info extra{};
363+
typename T::extra_info extra(row, extra_cols);
415364
auto elem = extract_elem(row, cc, elem_cols);
416-
extra.extract(row, extra_cols);
417365
auto tags = extract_tags(row, tag_cols);
418366
if (notify)
419367
notify(elem); // let callback function know about a new element we're processing
@@ -466,59 +414,4 @@ void extract_changesets(
466414
}
467415
}
468416

469-
std::vector<std::string> psql_array_to_vector(const pqxx::field& field) {
470-
return psql_array_to_vector(std::string_view(field.c_str(), field.size()));
471-
}
472417

473-
std::vector<std::string> psql_array_to_vector(std::string_view str) {
474-
std::vector<std::string> strs;
475-
std::string value;
476-
bool quotedValue = false;
477-
bool escaped = false;
478-
bool write = false;
479-
480-
if (str == "{NULL}" || str.empty())
481-
return strs;
482-
483-
const auto str_size = str.size();
484-
for (unsigned int i = 1; i < str_size; i++) {
485-
if (str[i] == ',') {
486-
if (quotedValue) {
487-
value += ',';
488-
} else {
489-
write = true;
490-
}
491-
} else if (str[i] == '"') {
492-
if (escaped) {
493-
value += '"';
494-
escaped = false;
495-
} else if (quotedValue) {
496-
quotedValue = false;
497-
} else {
498-
quotedValue = true;
499-
}
500-
} else if (str[i] == '\\') {
501-
if (escaped) {
502-
value += '\\';
503-
escaped = false;
504-
} else {
505-
escaped = true;
506-
}
507-
} else if (str[i] == '}') {
508-
if (quotedValue) {
509-
value += '}';
510-
} else {
511-
write = true;
512-
}
513-
} else {
514-
value += str[i];
515-
}
516-
517-
if (write) {
518-
strs.push_back(value);
519-
value.clear();
520-
write = false;
521-
}
522-
}
523-
return strs;
524-
}

0 commit comments

Comments
 (0)