Skip to content

Commit 060656a

Browse files
authored
Merge pull request #2276 from joto/protocol-level-prepare
Use protocol level prepare instead of PREPARE sql commands
2 parents 0becb10 + f4ace45 commit 060656a

File tree

7 files changed

+61
-27
lines changed

7 files changed

+61
-27
lines changed

src/expire-output.cpp

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -65,17 +65,19 @@ std::size_t expire_output_t::output_tiles_to_table(
6565

6666
if (result.num_fields() == 3) {
6767
// old format with fields: zoom, x, y
68-
db_connection.exec("PREPARE insert_tiles(int4, int4, int4) AS"
69-
" INSERT INTO {} (zoom, x, y) VALUES ($1, $2, $3)"
70-
" ON CONFLICT DO NOTHING",
71-
qn);
68+
db_connection.prepare("insert_tiles",
69+
"INSERT INTO {} (zoom, x, y)"
70+
" VALUES ($1::int4, $2::int4, $3::int4)"
71+
" ON CONFLICT DO NOTHING",
72+
qn);
7273
} else {
7374
// new format with fields: zoom, x, y, first, last
74-
db_connection.exec("PREPARE insert_tiles(int4, int4, int4) AS"
75-
" INSERT INTO {} (zoom, x, y) VALUES ($1, $2, $3)"
76-
" ON CONFLICT (zoom, x, y)"
77-
" DO UPDATE SET last = CURRENT_TIMESTAMP(0)",
78-
qn);
75+
db_connection.prepare("insert_tiles",
76+
"INSERT INTO {} (zoom, x, y)"
77+
" VALUES ($1::int4, $2::int4, $3::int4)"
78+
" ON CONFLICT (zoom, x, y)"
79+
" DO UPDATE SET last = CURRENT_TIMESTAMP(0)",
80+
qn);
7981
}
8082

8183
auto const count = for_each_tile(

src/flex-table.cpp

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -167,15 +167,12 @@ std::string flex_table_t::build_sql_prepare_get_wkb() const
167167

168168
if (has_multicolumn_id_index()) {
169169
return fmt::format(
170-
R"(PREPARE get_wkb_{}(char(1), bigint) AS)"
171-
R"( SELECT {} FROM {} WHERE "{}" = $1 AND "{}" = $2)",
172-
m_table_num, columns, full_name(), m_columns[0].name(),
173-
m_columns[1].name());
170+
R"(SELECT {} FROM {} WHERE "{}" = $1::char(1) AND "{}" = $2::bigint)",
171+
columns, full_name(), m_columns[0].name(), m_columns[1].name());
174172
}
175173

176-
return fmt::format(R"(PREPARE get_wkb_{}(bigint) AS)"
177-
R"( SELECT {} FROM {} WHERE "{}" = $1)",
178-
m_table_num, columns, full_name(), id_column_names());
174+
return fmt::format(R"(SELECT {} FROM {} WHERE "{}" = $1::bigint)", columns,
175+
full_name(), id_column_names());
179176
}
180177

181178
std::string
@@ -246,7 +243,8 @@ bool flex_table_t::has_columns_with_expire() const noexcept
246243
void flex_table_t::prepare(pg_conn_t const &db_connection) const
247244
{
248245
if (has_id_column() && has_columns_with_expire()) {
249-
db_connection.exec(build_sql_prepare_get_wkb());
246+
auto const stmt = fmt::format("get_wkb_{}", m_table_num);
247+
db_connection.prepare(stmt, fmt::runtime(build_sql_prepare_get_wkb()));
250248
}
251249
}
252250

src/middle-pgsql.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1105,10 +1105,11 @@ void middle_pgsql_t::update_users_table()
11051105
log_info("Writing {} entries to table '{}'...", m_users.size(),
11061106
m_users_table.name());
11071107

1108-
m_db_connection.exec("PREPARE insert_user(int8, text) AS"
1109-
" INSERT INTO {}.\"{}\" (id, name) VALUES ($1, $2)"
1110-
" ON CONFLICT (id) DO UPDATE SET id=EXCLUDED.id",
1111-
m_users_table.schema(), m_users_table.name());
1108+
m_db_connection.prepare(
1109+
"insert_user",
1110+
"INSERT INTO {}.\"{}\" (id, name) VALUES ($1::int8, $2::text)"
1111+
" ON CONFLICT (id) DO UPDATE SET id=EXCLUDED.id",
1112+
m_users_table.schema(), m_users_table.name());
11121113

11131114
for (auto const &[id, name] : m_users) {
11141115
m_db_connection.exec_prepared("insert_user", id, name);

src/pgsql.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,20 @@ void pg_conn_t::copy_end(std::string_view context) const
194194
}
195195
}
196196

197+
void pg_conn_t::prepare_internal(std::string_view stmt,
198+
std::string_view sql) const
199+
{
200+
if (get_logger().log_sql()) {
201+
log_sql("(C{}) PREPARE {} AS {}", m_connection_id, stmt, sql);
202+
}
203+
204+
pg_result_t const res{
205+
PQprepare(m_conn.get(), stmt.data(), sql.data(), 0, nullptr)};
206+
if (res.status() != PGRES_COMMAND_OK) {
207+
throw fmt_error("Prepare failed for '{}': {}.", sql, error_msg());
208+
}
209+
}
210+
197211
pg_result_t pg_conn_t::exec_prepared_internal(char const *stmt, int num_params,
198212
char const *const *param_values,
199213
int *param_lengths,

src/pgsql.hpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,24 @@ class pg_conn_t
179179
return exec(fmt::format(sql, std::forward<TArgs>(params)...));
180180
}
181181

182+
/**
183+
* Prepare SQL query.
184+
*
185+
* \param stmt Name of the prepared query.
186+
* \param sql SQL query.
187+
* \param params Any number of arguments for the fmt lib.
188+
* \throws std::runtime_exception If the command failed (didn't return
189+
* status code PGRES_COMMAND_OK).
190+
*/
191+
template <typename... TArgs>
192+
void prepare(std::string_view stmt, fmt::format_string<TArgs...> sql,
193+
TArgs... params) const
194+
{
195+
std::string const query =
196+
fmt::format(sql, std::forward<TArgs>(params)...);
197+
prepare_internal(stmt, query);
198+
}
199+
182200
/**
183201
* Run the named prepared SQL statement and return the results in text
184202
* format.
@@ -228,6 +246,8 @@ class pg_conn_t
228246
void close();
229247

230248
private:
249+
void prepare_internal(std::string_view stmt, std::string_view sql) const;
250+
231251
pg_result_t exec_prepared_internal(char const *stmt, int num_params,
232252
char const *const *param_values,
233253
int *param_lengths, int *param_formats,

src/properties.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -121,9 +121,9 @@ void properties_t::store()
121121

122122
pg_conn_t const db_connection{m_connection_params, "prop.store"};
123123

124-
db_connection.exec(
125-
"PREPARE set_property(text, text) AS"
126-
" INSERT INTO {} (property, value) VALUES ($1, $2)"
124+
db_connection.prepare(
125+
"set_property",
126+
"INSERT INTO {} (property, value) VALUES ($1::text, $2::text)"
127127
" ON CONFLICT (property) DO UPDATE SET value = EXCLUDED.value",
128128
table);
129129

src/table.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -143,9 +143,8 @@ void table_t::prepare()
143143
{
144144
//let postgres cache this query as it will presumably happen a lot
145145
auto const qual_name = qualified_name(m_target->schema(), m_target->name());
146-
m_db_connection->exec("PREPARE get_wkb(int8) AS"
147-
" SELECT way FROM {} WHERE osm_id = $1",
148-
qual_name);
146+
m_db_connection->prepare(
147+
"get_wkb", "SELECT way FROM {} WHERE osm_id = $1::int8", qual_name);
149148
}
150149

151150
void table_t::generate_copy_column_list()

0 commit comments

Comments
 (0)