Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,8 +99,9 @@ database dump, then you need to swap out the databases atomically:

This unfortunately means you need twice the space of the database for updates.

_WARNING: Never unpack the database in place of the old one. This will lead
to corrupted data._
> [!CAUTION]
> Never unpack the database in place of the old one. This will lead
> to corrupted data.


## Usage
Expand Down
60 changes: 43 additions & 17 deletions docs/usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,23 +84,46 @@ leads to cryptic errors in OpenSearch.

### Importing from a Nominatim database

The default mode is to import the database from a Nominatim PostgreSQL data.
> [!NOTE]
> Support for pgpass file available for Photon>=1.4.0.

The default mode is to import the database from a Nominatim PostgreSQL database.
To learn about Nominatim and how to set up a database refer
to the [installation documentation](https://nominatim.org/release-docs/latest/admin/Installation/).
to its [installation documentation](https://nominatim.org/release-docs/latest/admin/Installation/).

_Important: make sure that updates are stopped on the Nominatim database
when running the photon import or results are unpredictable._
> [!CAUTION]
> Make sure that updates are stopped on the Nominatim database
> when running the photon import or results are unpredictable.

photon will try to connect to a PostgreSQL server in the default location
(localhost at port 5432) using the user 'nominatim' and look for a database
'nominatim'. You can customize this with the parameters **-host**, **-port**,
**-user**, **-password**, and **-database**.
(localhost at port 5432) and look for a database 'nominatim'. You can
customize this with the parameters **-host**, **-port**,
**-user**, **-password**, and **-database** and/or supply a pgpass file

You likely will need to enable password authentication to the PostgreSQL database.
To do so, you can set a password for the database user like this:

psql -d nominatim -c "ALTER USER www-data WITH ENCRYPTED PASSWORD 'mysecretpassword'"

While you can then give the password to Photon on the command line, this is
_not recommended_ for security reasons. Use a
[pgpass file](https://www.postgresql.org/docs/current/libpq-pgpass.html)
instead: in the home directory of the user running the import command
create a file `.pgpass` and add the following line:

```
127.0.0.1:5432:nominatim:www-data:mysecretpassword
```

Naturally, you need to adapt the user name and password to what you actually
use. If necessary, also change the database name `nominatim`. You can now
leave out -user and -password parameters, when running Photon. They will
be picked up from the file when omitted.

If you need to put the pgpass file in a different location, then you may
specify the location by either setting the PGPASSFILE environment variable
or using the property `-Dorg.postgresql.pgpassfile=` on the command line.

The PostgreSQL user only needs read access to the query tables of the
Nominatim database (similar to
[Nominatim's web user](https://nominatim.org/release-docs/latest/customize/Settings/#nominatim_database_webuser)).
Expand All @@ -113,6 +136,7 @@ before starting the import with the following command:

Adapt the database name as required.


### Importing from a dump file

To load the photon database from a dump file (for example from the
Expand Down Expand Up @@ -149,10 +173,11 @@ When available, photon can also import full geometries instead of just a
centroid and bounding box. These geometries will then be returned with the
response. To enable this, use the **-full-geometries** switch.

_Hint: if these filtering options are not sufficient, it is always possible
to preprocess the json dump before feeding it to photon. Have a look at the
[dump spec](json-dump-format-0.1.0.md) to learn about the format of this
file._
> [!TIP]
> If these filtering options are not sufficient, it is always possible
> to preprocess the json dump before feeding it to photon. Have a look at the
> [dump spec](json-dump-format-0.1.0.md) to learn about the format of this
> file.

### Reverse-only mode

Expand Down Expand Up @@ -221,12 +246,13 @@ export NOMINATIM_DIR=/srv/nominatim/...

where `NOMINATIM_DIR` is the project directory of your Nominatim installation.

_WARNING: never make the /nominatim-update endpoint available on a public
network. While the endpoint is safe to be triggered by random requests,
updates nonetheless create load on your database and running updates while
Nominatim updates are in progress may lead to inconsistencies in the photon
database. You therefore would want to be able to control when exactly an
update is run._
> [!WARNING]
> Never make the /nominatim-update endpoint available on a public
> network. While the endpoint is safe to be triggered by random requests,
> updates nonetheless create load on your database and running updates while
> Nominatim updates are in progress may lead to inconsistencies in the photon
> database. You therefore would want to be able to control when exactly an
> update is run.

## Exporting Data to a JSON Dump

Expand Down
14 changes: 14 additions & 0 deletions src/main/java/de/komoot/photon/config/HostNameValidator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package de.komoot.photon.config;

import com.beust.jcommander.IParameterValidator;
import com.beust.jcommander.ParameterException;

public class HostNameValidator implements IParameterValidator {

@Override
public void validate(String name, String value) throws ParameterException {
if (value.matches(".*[,&/\\\\].*")) {
throw new ParameterException("Parameter " + name + " must not contain &, /, \\ or commas.");
Comment thread
lonvia marked this conversation as resolved.
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ public class IdentifierValidator implements IParameterValidator {

@Override
public void validate(String name, String value) throws ParameterException {
if (value.matches(".*[\\\"',.;$%&/()<>{}=?^*#].*")) {
if (value.matches(".*[\"',.;$%&/()<>{}=?^*#\\\\].*")) {
throw new ParameterException("Parameter " + name + " must not contain special characters.");
}
}
Expand Down
37 changes: 18 additions & 19 deletions src/main/java/de/komoot/photon/config/PostgresqlConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@
import com.beust.jcommander.Parameter;
import org.jspecify.annotations.NullMarked;
import org.jspecify.annotations.Nullable;
import org.postgresql.ds.PGSimpleDataSource;

@NullMarked
public class PostgresqlConfig {
public static final String GROUP = "PostgreSQL options";

@Parameter(names = "-host", category = GROUP, placeholder = "HOST", description = """
@Parameter(names = "-host", category = GROUP, placeholder = "HOST", validateWith = HostNameValidator.class, description = """
Hostname of the PostgreSQL database
""")
private String host = "127.0.0.1";
Expand All @@ -26,35 +27,33 @@ public class PostgresqlConfig {
@Parameter(names = "-user", category = GROUP, placeholder = "NAME", description = """
User for the PostgreSQL database
""")
private String user = "nominatim";
@Nullable private String user = null;

@Parameter(names = "-password", category = GROUP, placeholder = "PASSWORD", description = """
Password for the PostgreSQL user
Password for the PostgreSQL user (using parameter not recommended, use a pgpass file instead)
""")
@Nullable private String password = null;

public String getHost() {
return this.host;
}
public PGSimpleDataSource getDataSource() {
var dataSource = new PGSimpleDataSource();

public int getPort() {
return this.port;
}
dataSource.setDatabaseName(database);
dataSource.setServerNames(new String[]{host});
dataSource.setPortNumbers(new int[]{port});

public String getDatabase() {
return this.database;
}

public String getUser() {
return this.user;
}
if (user != null) {
dataSource.setUser(user);
}
if (password != null) {
dataSource.setPassword(password);
}

@Nullable public String getPassword() {
return this.password;
return dataSource;
}

@Override
public String toString() {
return String.format("database %s at %s:%d (user: %s)", database, host, port, user);
return String.format("database %s at %s:%d (user: %s)",
database, host, port, user == null ? "-" : user);
}
}
14 changes: 1 addition & 13 deletions src/main/java/de/komoot/photon/nominatim/NominatimConnector.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
import de.komoot.photon.nominatim.model.AddressRow;
import de.komoot.photon.nominatim.model.AddressType;
import de.komoot.photon.nominatim.model.NameMap;
import org.apache.commons.dbcp2.BasicDataSource;
import org.jspecify.annotations.NullMarked;
import org.jspecify.annotations.Nullable;
import org.springframework.jdbc.core.JdbcTemplate;
Expand All @@ -27,17 +26,7 @@ public class NominatimConnector {
@Nullable private Boolean hasNewPostcodeLocationsTable;

protected NominatimConnector(PostgresqlConfig cfg, DBDataAdapter dataAdapter, DatabaseProperties dbProperties) {
BasicDataSource dataSource = new BasicDataSource();

dataSource.setUrl(String.format("jdbc:postgresql://%s:%d/%s",
cfg.getHost(), cfg.getPort(), cfg.getDatabase()));
dataSource.setUsername(cfg.getUser());

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed autocommit breaks cursors

High Severity

Replacing BasicDataSource with PGSimpleDataSource drops the previous setDefaultAutoCommit(false) setup. With autocommit on, PostgreSQL JDBC ignores the connector’s large fetchSize, so Nominatim import queries that stream outside TransactionTemplate can load whole country result sets in memory and risk OOM or failed imports.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 709a827. Configure here.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PGSimpleDataSource doesn't have a setDefaultAutoCommit function. And the source code seems to indicate that the default for autocommit is false. However, the part on ignoring fetchSize might have merit from what I see in the planet import. Need to investigate.

if (cfg.getPassword() != null) {
dataSource.setPassword(cfg.getPassword());
}

// Keep disabled or server-side cursors won't work.
dataSource.setDefaultAutoCommit(false);
var dataSource = cfg.getDataSource();

txTemplate = new TransactionTemplate(new DataSourceTransactionManager(dataSource));

Expand All @@ -46,7 +35,6 @@ protected NominatimConnector(PostgresqlConfig cfg, DBDataAdapter dataAdapter, Da

dbutils = dataAdapter;
this.dbProperties = dbProperties;

}

@Nullable
Expand Down