From a743d364be26b338b37222bfcc83db4a0adb3d16 Mon Sep 17 00:00:00 2001 From: Paul Norman Date: Mon, 9 Feb 2015 19:32:25 -0800 Subject: [PATCH] Add an option to specify the target schema for import This allows a custom schema to be used, or for users where a different search_path is set, the public schema to be used. --- README.md | 2 +- docs/osm2pgsql.1 | 3 +++ docs/usage.md | 6 +++++- middle-pgsql.cpp | 2 ++ options.cpp | 11 ++++++++--- options.hpp | 1 + output-gazetteer.cpp | 10 ++++++++++ output-multi.cpp | 3 ++- output-pgsql.cpp | 2 +- table.cpp | 10 +++++++--- table.hpp | 3 ++- tests/test-parse-options.cpp | 3 +++ 12 files changed, 45 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 2158e7f99..bda2044e7 100644 --- a/README.md +++ b/README.md @@ -87,7 +87,7 @@ On FreeBSD instead bootstrap and then run ## Usage ## -Osm2pgsql has one program, the executable itself, which has **43** command line +Osm2pgsql has one program, the executable itself, which has **44** command line options. Before loading into a database, the database must be created and the PostGIS diff --git a/docs/osm2pgsql.1 b/docs/osm2pgsql.1 index 4d96a5dc8..5ad33fa02 100644 --- a/docs/osm2pgsql.1 +++ b/docs/osm2pgsql.1 @@ -72,6 +72,9 @@ Store the slim mode tables in the given tablespace. \fB\ \fR\-\-tablespace\-slim\-index tablespacename Store the indices of the slim mode tables in the given tablespace. .TP +\fB\-X\fR|\-\-schema +Use the specified schema to store the tables +.TP \fB\-l\fR|\-\-latlong Store data in degrees of latitude & longitude. .TP diff --git a/docs/usage.md b/docs/usage.md index 1cc6c02e2..7e148415e 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -1,6 +1,6 @@ # Command-line usage # -Osm2pgsql has one program, the executable itself, which has **43** command line +Osm2pgsql has one program, the executable itself, which has **44** command line options. A full list of options can be obtained with ``osm2pgsql -h -v``. This document provides an overview of options, and more importantly, why you might use them. @@ -48,6 +48,10 @@ osm2pgsql supports standard options for how to connect to PostgreSQL. If left unset, it will attempt to connect to the ``gis`` database using a unix socket. Most usage only requires setting ``--database``. +``--schema`` allows a [PostgreSQL schema](http://www.postgresql.org/docs/current/static/ddl-schemas.html) +to be set. This is similar to creating a dedicated user for osm2pgsql and using +``ALTER ROLE ... SET search_path TO ...``. + ``--tablespace`` options allow the location of main and slim tables and indexes to be set to different tablespaces independently, typically on machines with multiple drive arrays where one is not large enough for all of the database. diff --git a/middle-pgsql.cpp b/middle-pgsql.cpp index bdd8b3c5a..df0c1e0b2 100644 --- a/middle-pgsql.cpp +++ b/middle-pgsql.cpp @@ -1074,6 +1074,8 @@ int middle_pgsql_t::connect(table_desc& table) { fprintf(stderr, "Connection to database failed: %s\n", PQerrorMessage(sql_conn)); return 1; } + + pgsql_exec_simple(sql_conn, PGRES_COMMAND_OK, (boost::format("SET search_path TO %1%,public;") % out_options->schema.get()).str()); table.sql_conn = sql_conn; return 0; } diff --git a/options.cpp b/options.cpp index 6691ca2a5..fd6136e87 100644 --- a/options.cpp +++ b/options.cpp @@ -16,7 +16,7 @@ namespace { - const char * short_options = "ab:cd:KhlmMp:suvU:WH:P:i:IE:C:S:e:o:O:xkjGz:r:V"; + const char * short_options = "ab:cd:KhlmMp:suvU:WH:P:X:i:IE:C:S:e:o:O:xkjGz:r:V"; const struct option long_options[] = { {"append", 0, 0, 'a'}, @@ -36,6 +36,7 @@ namespace {"password", 0, 0, 'W'}, {"host", 1, 0, 'H'}, {"port", 1, 0, 'P'}, + {"schema", 1, 0, 'X'}, {"tablespace-index", 1, 0, 'i'}, {"tablespace-slim-data", 1, 0, 200}, {"tablespace-slim-index", 1, 0, 201}, @@ -107,7 +108,8 @@ namespace environment variable or use -W).\n\ -W|--password Force password prompt.\n\ -H|--host Database server host name or socket location.\n\ - -P|--port Database server port.\n"); + -P|--port Database server port.\n\ + -X|--schema Database target schema.\n"); if (verbose) { @@ -271,7 +273,7 @@ options_t::options_t(): tag_transform_script(boost::none), tag_transform_node_func(boost::none), tag_transform_way_func(boost::none), tag_transform_rel_func(boost::none), tag_transform_rel_mem_func(boost::none), create(0), sanitize(0), long_usage_bool(0), pass_prompt(0), db("gis"), username(boost::none), host(boost::none), - password(boost::none), port("5432"), output_backend("pgsql"), input_reader("auto"), bbox(boost::none), extra_attributes(0), verbose(0) + password(boost::none), port("5432"), schema(boost::none), output_backend("pgsql"), input_reader("auto"), bbox(boost::none), extra_attributes(0), verbose(0) { } @@ -349,6 +351,9 @@ options_t options_t::parse(int argc, char *argv[]) case 'P': options.port = optarg; break; + case 'X': + options.schema = optarg; + break; case 'S': options.style = optarg; break; diff --git a/options.hpp b/options.hpp index 84cb9cf44..4353464fb 100644 --- a/options.hpp +++ b/options.hpp @@ -74,6 +74,7 @@ struct options_t { boost::optional host; boost::optional password; std::string port; + boost::optional schema; std::string output_backend ; std::string input_reader; boost::optional bbox; diff --git a/output-gazetteer.cpp b/output-gazetteer.cpp index 6329410aa..ab9c13ef8 100644 --- a/output-gazetteer.cpp +++ b/output-gazetteer.cpp @@ -593,6 +593,11 @@ int output_gazetteer_t::connect() { return 1; } + if (m_options.schema) + { + pgsql_exec_simple(Connection, PGRES_COMMAND_OK, (boost::format("SET search_path TO %1%,public;") % m_options.schema.get()).str()); + } + if (m_options.append) { ConnectionDelete = PQconnectdb(m_options.conninfo.c_str()); if (PQstatus(ConnectionDelete) != CONNECTION_OK) @@ -601,6 +606,11 @@ int output_gazetteer_t::connect() { return 1; } + if (m_options.schema) + { + pgsql_exec_simple(ConnectionDelete, PGRES_COMMAND_OK, (boost::format("SET search_path TO %1%,public;") % m_options.schema.get()).str()); + } + pgsql_exec(ConnectionDelete, PGRES_COMMAND_OK, "PREPARE get_classes (CHAR(1), " POSTGRES_OSMID_TYPE ") AS SELECT class FROM place WHERE osm_type = $1 and osm_id = $2"); } return 0; diff --git a/output-multi.cpp b/output-multi.cpp index 9a0fbd9a6..a670beb90 100644 --- a/output-multi.cpp +++ b/output-multi.cpp @@ -22,7 +22,8 @@ output_multi_t::output_multi_t(const std::string &name, m_options.hstore_columns, m_processor->srid(), m_options.scale, m_options.append, m_options.slim, m_options.droptemp, m_options.hstore_mode, m_options.enable_hstore_index, - m_options.tblsmain_data, m_options.tblsmain_index)), + m_options.tblsmain_data, m_options.tblsmain_index, + m_options.schema)), ways_pending_tracker(new id_tracker()), ways_done_tracker(new id_tracker()), rels_pending_tracker(new id_tracker()), m_expire(new expire_tiles(&m_options)) { } diff --git a/output-pgsql.cpp b/output-pgsql.cpp index 8add8a0ff..5ce663def 100644 --- a/output-pgsql.cpp +++ b/output-pgsql.cpp @@ -714,7 +714,7 @@ output_pgsql_t::output_pgsql_t(const middle_query_t* mid_, const options_t &opti new table_t( m_options.conninfo, name, type, columns, m_options.hstore_columns, SRID, m_options.scale, m_options.append, m_options.slim, m_options.droptemp, m_options.hstore_mode, - m_options.enable_hstore_index, m_options.tblsmain_data, m_options.tblsmain_index + m_options.enable_hstore_index, m_options.tblsmain_data, m_options.tblsmain_index, m_options.schema ) )); } diff --git a/table.cpp b/table.cpp index 3be6ea92d..a8af59306 100644 --- a/table.cpp +++ b/table.cpp @@ -12,10 +12,10 @@ using std::string; table_t::table_t(const string& conninfo, const string& name, const string& type, const columns_t& columns, const hstores_t& hstore_columns, const int srid, const int scale, const bool append, const bool slim, const bool drop_temp, const int hstore_mode, - const bool enable_hstore_index, const boost::optional& table_space, const boost::optional& table_space_index) : + const bool enable_hstore_index, const boost::optional& table_space, const boost::optional& table_space_index, const boost::optional& schema) : conninfo(conninfo), name(name), type(type), sql_conn(NULL), copyMode(false), srid((fmt("%1%") % srid).str()), scale(scale), append(append), slim(slim), drop_temp(drop_temp), hstore_mode(hstore_mode), enable_hstore_index(enable_hstore_index), - columns(columns), hstore_columns(hstore_columns), table_space(table_space), table_space_index(table_space_index) + columns(columns), hstore_columns(hstore_columns), table_space(table_space), table_space_index(table_space_index), schema(schema) { //if we dont have any columns if(columns.size() == 0) @@ -34,7 +34,7 @@ table_t::table_t(const table_t& other): conninfo(other.conninfo), name(other.name), type(other.type), sql_conn(NULL), copyMode(false), buffer(), srid(other.srid), scale(other.scale), append(other.append), slim(other.slim), drop_temp(other.drop_temp), hstore_mode(other.hstore_mode), enable_hstore_index(other.enable_hstore_index), columns(other.columns), hstore_columns(other.hstore_columns), copystr(other.copystr), table_space(other.table_space), - table_space_index(other.table_space_index), single_fmt(other.single_fmt), point_fmt(other.point_fmt), del_fmt(other.del_fmt) + table_space_index(other.table_space_index), schema(other.schema), single_fmt(other.single_fmt), point_fmt(other.point_fmt), del_fmt(other.del_fmt) { // if the other table has already started, then we want to execute // the same stuff to get into the same state. but if it hasn't, then @@ -89,6 +89,10 @@ void table_t::connect() sql_conn = _conn; //let commits happen faster by delaying when they actually occur pgsql_exec_simple(sql_conn, PGRES_COMMAND_OK, "SET synchronous_commit TO off;"); + if (schema) + { + pgsql_exec_simple(sql_conn, PGRES_COMMAND_OK, (fmt("SET search_path TO %1%,public;") % schema.get()).str()); + } } void table_t::start() diff --git a/table.hpp b/table.hpp index 0e38def47..388d7c2a4 100644 --- a/table.hpp +++ b/table.hpp @@ -20,7 +20,7 @@ class table_t public: table_t(const std::string& conninfo, const std::string& name, const std::string& type, const columns_t& columns, const hstores_t& hstore_columns, const int srid, const int scale, const bool append, const bool slim, const bool droptemp, const int hstore_mode, const bool enable_hstore_index, - const boost::optional& table_space, const boost::optional& table_space_index); + const boost::optional& table_space, const boost::optional& table_space_index, const boost::optional& schema); table_t(const table_t& other); ~table_t(); @@ -83,6 +83,7 @@ class table_t std::string copystr; boost::optional table_space; boost::optional table_space_index; + boost::optional schema; fmt single_fmt, point_fmt, del_fmt; }; diff --git a/tests/test-parse-options.cpp b/tests/test-parse-options.cpp index 8cc57ee91..b21a5ed8a 100644 --- a/tests/test-parse-options.cpp +++ b/tests/test-parse-options.cpp @@ -241,6 +241,9 @@ void test_random_perms() add_arg_and_val_or_not("--number-processes", args, options.num_procs, rand() % 12); + if (options.schema) { + add_arg_and_val_or_not("--schema", args, options.schema->c_str(), get_random_string(6)); + } //add_arg_or_not("--disable-parallel-indexing", args, options.parallel_indexing); add_arg_or_not("--unlogged", args, options.unlogged);