Skip to content

Commit f543502

Browse files
authored
fix: handle localized duplicate-database errors on restart (#13) (#15)
`pg0 start` failed to restart an existing instance when PostgreSQL returned a localized duplicate-database error (e.g. on Windows with a Chinese locale: `数据库 "x" 已经存在`). The previous logic relied on the English substring `already exists` to swallow the error, which never matched on non-English builds. Replaced the post-hoc string match with a `database_exists()` pre-check so the create path is locale-independent, and added a Python regression test that starts → stops → restarts an instance with a custom database.
1 parent 0426f8c commit f543502

2 files changed

Lines changed: 29 additions & 7 deletions

File tree

sdk/python/tests/test_pg0.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,29 @@ def test_port_conflict_error(self, clean_instance):
152152
pg2.stop()
153153
pg0.drop(f"{TEST_NAME}-2")
154154

155+
def test_restart_with_custom_database(self, clean_instance):
156+
"""Restarting an instance with a non-default database must be idempotent.
157+
158+
Regression test for https://github.com/vectorize-io/pg0/issues/13
159+
Previously, the second start failed because pg0 only matched the English
160+
substring "already exists" when CREATE DATABASE returned a duplicate
161+
error, so restarts on PostgreSQL builds with a non-English lc_messages
162+
(e.g. Chinese on Windows: `数据库 "x" 已经存在`) crashed startup.
163+
"""
164+
pg = Pg0(name=TEST_NAME, port=TEST_PORT, database="testdb")
165+
pg.start()
166+
pg.execute("CREATE TABLE restart_test (id int);")
167+
pg.execute("INSERT INTO restart_test VALUES (42);")
168+
pg.stop()
169+
170+
# Second start must succeed and preserve data
171+
info = pg.start()
172+
assert info.running is True
173+
assert "testdb" in info.uri
174+
result = pg.execute("SELECT id FROM restart_test;")
175+
assert "42" in result
176+
pg.stop()
177+
155178
@pytest.mark.skipif(
156179
sys.platform == "win32",
157180
reason="signal.SIGKILL does not exist on Windows; crash-recovery behavior is exercised by the Unix matrix.",

src/main.rs

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -893,13 +893,12 @@ fn start(
893893

894894
// Create the database if it doesn't exist and it's not the default 'postgres'
895895
if database != "postgres" {
896-
println!("Creating database '{}'...", database);
897-
if let Err(e) = postgresql.create_database(&database) {
898-
// Ignore error if database already exists
899-
let err_str = e.to_string();
900-
if !err_str.contains("already exists") {
901-
return Err(e.into());
902-
}
896+
// Pre-check existence rather than relying on the duplicate-database error
897+
// string, which is localized by PostgreSQL's lc_messages (e.g. on Windows
898+
// with a Chinese locale: `数据库 "x" 已经存在`). See vectorize-io/pg0#13.
899+
if !postgresql.database_exists(&database)? {
900+
println!("Creating database '{}'...", database);
901+
postgresql.create_database(&database)?;
903902
}
904903
// Grant privileges to the user on the database
905904
if username != "postgres" {

0 commit comments

Comments
 (0)