Skip to content

Commit c1853c8

Browse files
committed
Merge remote-tracking branch 'origin/master' into copilot/fix-621
2 parents acfa6d4 + 1c40705 commit c1853c8

File tree

6 files changed

+44
-17
lines changed

6 files changed

+44
-17
lines changed

.github/copilot-instructions.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,9 @@ Run tests in multiple configurations:
3737

3838
- `hatch test` – unit test runner for all matrix environments
3939
- `hatch test --python 3.12` – isolate matrix to Python 3.12 set
40-
- `hatch run functional:all` – functional backup/restore (SQLite + PostgreSQL)
41-
- `hatch run functional:sqlite --all` – functional (SQLite only)
42-
- `hatch run functional:postgres --all` – functional (PostgreSQL only)
40+
- `hatch run functional:all -v` – functional backup/restore (SQLite + PostgreSQL)
41+
- `hatch run functional:sqlite --all -v` – functional (SQLite only)
42+
- `hatch run functional:postgres --all -v` – functional (PostgreSQL only)
4343
- `hatch run lint:check` – linting
4444
- `hatch run lint:format` – auto-format (Ruff)
4545

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ Don't forget to remove deprecated code on each major release!
4747
- Fix SQLite `no such table` errors.
4848
- Fix SQLite `UNIQUE constraint` errors.
4949
- Fix SQLite `index`/`trigger`/`view` `<NAME> already exists` errors.
50+
- Fix PostgreSQL restore errors with identity columns by automatically enabling `--if-exists` when using `--clean` in `PgDumpBinaryConnector`.
5051

5152
### Security
5253

dbbackup/db/postgresql.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,7 @@ def _restore_dump(self, dump: str):
166166
for schema in self.schemas:
167167
cmd.extend(["-n", schema])
168168

169-
if self.if_exists:
169+
if self.if_exists or self.drop:
170170
cmd.extend(["--if-exists"])
171171

172172
if self.restore_suffix:

docs/src/databases.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ All PostgreSQL connectors have the following settings:
113113
| ------------------ | --------------------------------------------------------------------------------------------------------------------------------------- | ------- |
114114
| SINGLE_TRANSACTION | Wrap restore in a single transaction so errors cause full rollback (`--single-transaction` for `psql` / `pg_restore`). | `True` |
115115
| DROP | Include / execute drop statements when restoring (`--clean` with `pg_dump` / `pg_restore`). In binary mode drops happen during restore. | `True` |
116-
| IF_EXISTS | Add `IF EXISTS` to destructive statements in clean mode. | `False` |
116+
| IF_EXISTS | Add `IF EXISTS` to destructive statements in clean mode. Automatically enabled when `DROP=True` to prevent identity column errors. | `False` |
117117

118118
#### PgDumpConnector
119119

scripts/_utils.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
Provided symbol keys:
1414
PASS, FAIL, SUMMARY, TEST, PG, MYSQL
1515
16-
The ``PG`` key is only used by the PostgreSQL live test; ``MYSQL`` is only
16+
The ``PG`` key is only used by the PostgreSQL live test; ``MYSQL`` is only
1717
used by the MySQL live test; others are shared.
1818
"""
1919

@@ -32,12 +32,12 @@
3232
}
3333

3434
_ASCII_SYMBOLS = {
35-
"PASS": "",
36-
"FAIL": "",
37-
"SUMMARY": "",
38-
"TEST": "",
39-
"PG": "",
40-
"MYSQL": "",
35+
"PASS": "PASS:",
36+
"FAIL": "FAIL:",
37+
"SUMMARY": "SUMMARY:",
38+
"TEST": "TEST:",
39+
"PG": ">>",
40+
"MYSQL": ">>",
4141
}
4242

4343

tests/test_connectors/test_postgresql.py

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -220,14 +220,40 @@ def test_create_dump_drop(self, mock_dump_cmd):
220220

221221
def test_create_dump_if_exists(self, mock_run_command):
222222
dump = self.connector.create_dump()
223-
# Without
223+
# Test explicit if_exists=True behavior
224+
self.connector.if_exists = True
225+
self.connector.drop = False # Disable automatic --if-exists from --clean
226+
self.connector.restore_dump(dump)
227+
cmd_args = mock_run_command.call_args[0][0]
228+
self.assertNotIn(" --clean", cmd_args)
229+
self.assertIn(" --if-exists", cmd_args)
230+
231+
# Test that if_exists=False with drop=False means no --if-exists
224232
self.connector.if_exists = False
233+
self.connector.drop = False
225234
self.connector.restore_dump(dump)
226-
self.assertNotIn(" --if-exists", mock_run_command.call_args[0][0])
227-
# With
228-
self.connector.if_exists = True
235+
cmd_args = mock_run_command.call_args[0][0]
236+
self.assertNotIn(" --clean", cmd_args)
237+
self.assertNotIn(" --if-exists", cmd_args)
238+
239+
def test_clean_automatically_enables_if_exists(self, mock_run_command):
240+
"""Test that --if-exists is automatically added when using --clean to prevent identity column errors."""
241+
dump = self.connector.create_dump()
242+
# When drop=True (which adds --clean), --if-exists should be automatically added
243+
self.connector.drop = True
244+
self.connector.if_exists = False # Explicitly set to False
229245
self.connector.restore_dump(dump)
230-
self.assertIn(" --if-exists", mock_run_command.call_args[0][0])
246+
cmd_args = mock_run_command.call_args[0][0]
247+
self.assertIn(" --clean", cmd_args)
248+
self.assertIn(" --if-exists", cmd_args)
249+
250+
# When drop=False, --if-exists should not be added automatically
251+
self.connector.drop = False
252+
self.connector.if_exists = False
253+
self.connector.restore_dump(dump)
254+
cmd_args = mock_run_command.call_args[0][0]
255+
self.assertNotIn(" --clean", cmd_args)
256+
self.assertNotIn(" --if-exists", cmd_args)
231257

232258
def test_pg_options(self, mock_run_command):
233259
dump = self.connector.create_dump()

0 commit comments

Comments
 (0)