Connecting to databases with non-standard characters in the db name fails.
let connection_uri = "postgres://postgres:postgres@localhost:5432/test db";
let mut connection = PgConnection::connect(connection_uri).await?;
let results = sqlx::query("SELECT * FROM test")
.fetch_all(&mut connection)
.await?;
Fails with database "test%20db" does not exist
Creating a connection configuration, and then setting the db name explicitly, fixes the issue:
let connection_uri = "postgres://postgres:postgres@localhost:5432/test db";
let connect_options = PgConnectOptions::from_url(&connection_uri.parse()?)?;
let connect_options = connect_options.database("test db");
let mut connection = PgConnection::connect_with(&connect_options).await?;
let results = sqlx::query("SELECT * FROM test")
.fetch_all(&mut connection)
.await?;
Additionally, setting the db name with a query parameter also fixes the problem:
let connection_uri = "postgres://postgres:postgres@localhost:5432?dbname=test db";
Background
When parsing a connection string, the various parts are url decoded before being stored in the connection configuration struct.
When building back a URL, it seems we rely on the behavior of the set_path path method which will encode the string if needed, (if we passed the name using the dbname query param), or leave it as is if already percent encoded (if we passed it using the url path)
However, it looks like the establish method does not handle getting a url encoded database name, and sends it as-is. Hence our problem.
Fix
URL decode the db name when extracted from the path of a connection string
The problem
Connecting to databases with non-standard characters in the db name fails.
Fails with
database "test%20db" does not exist
Creating a connection configuration, and then setting the db name explicitly, fixes the issue:
Additionally, setting the db name with a query parameter also fixes the problem:
Background
When parsing a connection string, the various parts are url decoded before being stored in the connection configuration struct.
The one exception is the database name.
When we get the name from the
dbname
query param, it seems the values are decoded.When building back a URL, it seems we rely on the behavior of the
set_path
path method which will encode the string if needed, (if we passed the name using the dbname query param), or leave it as is if already percent encoded (if we passed it using the url path)However, it looks like the
establish
method does not handle getting a url encoded database name, and sends it as-is. Hence our problem.Fix
URL decode the db name when extracted from the path of a connection string