Skip to content

Commit 97bd724

Browse files
authored
Merge pull request #1185 from joto/schema-support-flex-output
Finish schema support in flex output
2 parents 0beb10f + aa9790d commit 97bd724

File tree

11 files changed

+100
-23
lines changed

11 files changed

+100
-23
lines changed

docs/flex.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,8 @@ With the `osm2pgsql.define_table()` function you can also define tables that
6969
additional column.
7070
* are in a specific PostgresSQL tablespace (set `data_tablespace`) or that
7171
get their indexes created in a specific tablespace (set `index_tablespace`).
72+
* are in a specific schema (set `schema`). Note that the schema has to be
73+
created before you start osm2pgsql.
7274

7375
If you are using the `osm2pgsql.define_(node|way|relation|area)_table()`
7476
convenience functions, osm2pgsql will automatically create an id column named

flex-config/with-schema.lua

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
2+
-- This configuration for the flex output shows how to define a table in
3+
-- a PostgreSQL schema.
4+
5+
local dtable = osm2pgsql.define_table{
6+
name = "data",
7+
schema = "myschema",
8+
ids = { type = 'way', id_column = 'way_id' },
9+
columns = {
10+
{ column = 'attrs', type = 'hstore' },
11+
{ column = 'tags', type = 'hstore' },
12+
{ column = 'geom', type = 'geometry' },
13+
}
14+
}
15+
16+
function osm2pgsql.process_way(object)
17+
dtable:add_row({
18+
tags = object.tags,
19+
geom = { create = 'line' }
20+
})
21+
end
22+

src/db-copy.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -177,12 +177,13 @@ void db_copy_thread_t::thread_t::start_copy(
177177
{
178178
assert(!m_inflight);
179179

180+
auto const qname = qualified_name(target->schema, target->name);
180181
fmt::memory_buffer sql;
181-
sql.reserve(target->name.size() + target->rows.size() + 14);
182+
sql.reserve(qname.size() + target->rows.size() + 20);
182183
if (target->rows.empty()) {
183-
fmt::format_to(sql, FMT_STRING("COPY {} FROM STDIN"), target->name);
184+
fmt::format_to(sql, FMT_STRING("COPY {} FROM STDIN"), qname);
184185
} else {
185-
fmt::format_to(sql, FMT_STRING("COPY {} ({}) FROM STDIN"), target->name,
186+
fmt::format_to(sql, FMT_STRING("COPY {} ({}) FROM STDIN"), qname,
186187
target->rows);
187188
}
188189

src/db-copy.hpp

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,15 @@
1111
#include <vector>
1212

1313
#include "osmtypes.hpp"
14-
15-
class pg_conn_t;
14+
#include "pgsql.hpp"
1615

1716
/**
1817
* Table information necessary for building SQL queries.
1918
*/
2019
struct db_target_descr_t
2120
{
21+
/// Schema of the target table (can be empty for default schema)
22+
std::string schema;
2223
/// Name of the target table for the copy operation.
2324
std::string name;
2425
/// Comma-separated list of rows for copy operation (when empty: all rows)
@@ -31,7 +32,8 @@ struct db_target_descr_t
3132
*/
3233
bool same_copy_target(db_target_descr_t const &other) const noexcept
3334
{
34-
return (this == &other) || (name == other.name && rows == other.rows);
35+
return (this == &other) || (schema == other.schema &&
36+
name == other.name && rows == other.rows);
3537
}
3638

3739
db_target_descr_t() = default;
@@ -190,7 +192,8 @@ class db_cmd_copy_delete_t : public db_cmd_copy_t
190192
void delete_data(pg_conn_t *conn) override
191193
{
192194
if (m_deleter.has_data()) {
193-
m_deleter.delete_rows(target->name, target->id, conn);
195+
m_deleter.delete_rows(qualified_name(target->schema, target->name),
196+
target->id, conn);
194197
}
195198
}
196199

src/flex-table.cpp

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -45,12 +45,12 @@ std::string flex_table_t::id_column_names() const
4545

4646
std::string flex_table_t::full_name() const
4747
{
48-
return "\"" + schema() + "\".\"" + name() + "\"";
48+
return qualified_name(schema(), name());
4949
}
5050

5151
std::string flex_table_t::full_tmp_name() const
5252
{
53-
return "\"" + schema() + "\".\"" + name() + "_tmp\"";
53+
return qualified_name(schema(), name() + "_tmp");
5454
}
5555

5656
flex_table_column_t &flex_table_t::add_column(std::string const &name,
@@ -162,11 +162,6 @@ void table_connection_t::start(bool append)
162162
m_db_connection->exec("RESET client_min_messages");
163163

164164
if (!append) {
165-
if (table().schema() != "public") {
166-
m_db_connection->exec(
167-
"CREATE SCHEMA IF NOT EXISTS \"{}\""_format(table().schema()));
168-
}
169-
170165
m_db_connection->exec(table().build_sql_create_table(
171166
table().has_geom_column() ? flex_table_t::table_type::interim
172167
: flex_table_t::table_type::permanent,
@@ -299,7 +294,7 @@ void table_connection_t::stop(bool updateable, bool append)
299294
}
300295

301296
fmt::print(stderr, "Analyzing table '{}'...\n", table().name());
302-
m_db_connection->exec("ANALYZE \"{}\""_format(table().name()));
297+
m_db_connection->exec("ANALYZE " + table().full_name());
303298

304299
fmt::print(stderr, "All postprocessing on table '{}' done in {}s.\n",
305300
table().name(), timer.stop());

src/flex-table.hpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,9 @@ class table_connection_t
199199
table->name(), table->id_column_names(),
200200
table->build_sql_column_list())),
201201
m_copy_mgr(copy_thread), m_db_connection(nullptr)
202-
{}
202+
{
203+
m_target->schema = table->schema();
204+
}
203205

204206
void connect(std::string const &conninfo);
205207

src/output-flex.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -593,18 +593,18 @@ flex_table_t &output_flex_t::create_flex_table()
593593
// optional "data_tablespace" field
594594
lua_getfield(lua_state(), -1, "data_tablespace");
595595
if (lua_isstring(lua_state(), -1)) {
596-
std::string const schema = lua_tostring(lua_state(), -1);
597-
check_name(schema, "data_tablespace");
598-
new_table.set_data_tablespace(schema);
596+
std::string const tablespace = lua_tostring(lua_state(), -1);
597+
check_name(tablespace, "data_tablespace");
598+
new_table.set_data_tablespace(tablespace);
599599
}
600600
lua_pop(lua_state(), 1);
601601

602602
// optional "index_tablespace" field
603603
lua_getfield(lua_state(), -1, "index_tablespace");
604604
if (lua_isstring(lua_state(), -1)) {
605-
std::string const schema = lua_tostring(lua_state(), -1);
606-
check_name(schema, "index_tablespace");
607-
new_table.set_index_tablespace(schema);
605+
std::string const tablespace = lua_tostring(lua_state(), -1);
606+
check_name(tablespace, "index_tablespace");
607+
new_table.set_index_tablespace(tablespace);
608608
}
609609
lua_pop(lua_state(), 1);
610610

src/pgsql.cpp

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,10 +149,28 @@ std::string tablespace_clause(std::string const &name)
149149
std::string sql;
150150

151151
if (!name.empty()) {
152-
sql += " TABLESPACE ";
152+
sql += " TABLESPACE \"";
153153
sql += name;
154+
sql += '"';
154155
}
155156

156157
return sql;
157158
}
158159

160+
std::string qualified_name(std::string const &schema, std::string const &name)
161+
{
162+
std::string result{"\""};
163+
164+
if (!schema.empty()) {
165+
result.reserve(schema.size() + name.size() + 5);
166+
result += schema;
167+
result += "\".\"";
168+
} else {
169+
result.reserve(name.size() + 2);
170+
}
171+
172+
result += name;
173+
result += '"';
174+
175+
return result;
176+
}

src/pgsql.hpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,16 @@ class pg_conn_t
142142
std::unique_ptr<PGconn, pg_conn_deleter_t> m_conn;
143143
};
144144

145+
/**
146+
* Return a TABLESPACE clause with the specified tablespace name or an empty
147+
* string if the name is empty.
148+
*/
145149
std::string tablespace_clause(std::string const &name);
146150

151+
/**
152+
* Return the possibly schema-qualified name of a table. Names are enclosed
153+
* in double quotes.
154+
*/
155+
std::string qualified_name(std::string const &schema, std::string const &name);
156+
147157
#endif // OSM2PGSQL_PGSQL_HPP

tests/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ set_test(test-output-pgsql-validgeom)
6060
set_test(test-output-pgsql-z_order)
6161
set_test(test-parse-osmium)
6262
set_test(test-persistent-cache LABELS NoDB)
63+
set_test(test-pgsql)
6364
set_test(test-ram-cache LABELS NoDB)
6465
set_test(test-taginfo LABELS NoDB)
6566
set_test(test-util LABELS NoDB)

0 commit comments

Comments
 (0)