feat: add restore-local-db command for restoring local databases from SQL dumps#597
feat: add restore-local-db command for restoring local databases from SQL dumps#597
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 3898894f85
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
Pull request overview
Adds a new Typer CLI command (restore-local-db) to restore a local PostgreSQL database from a SQL dump (local file or GCS gs:// URI), including sanitization of role/privilege statements and schema reset prior to restore.
Changes:
- Add
cli/db_restore.pyimplementing staging (local/GCS), optional gzip expansion, SQL sanitization, schema reset, andpsql -finvocation. - Register new
restore-local-dbcommand incli/cli.py, plus documentation updates incli/README.mdand rootREADME.md. - Add CLI test coverage for success paths and common failure modes (invalid source, remote host, schema reset failure,
psqlfailure, GCS.sql.gz).
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
cli/db_restore.py |
New restore implementation: validates target is local, stages dump (incl. GCS/gzip), sanitizes role-dependent SQL, resets schema, runs psql. |
cli/cli.py |
Adds restore-local-db Typer command wrapper around restore_local_db_from_sql. |
tests/test_cli_commands.py |
Adds unit tests covering restore invocation, input validation, host safety checks, schema reset errors, psql errors, and GCS gzip path. |
cli/README.md |
Documents the new command usage examples. |
README.md |
Documents running the new restore command in local/docker dev context. |
transfers/waterlevels_transducer_transfer.py |
Introduces an input row limit in _get_dfs (unrelated to restore-local-db). |
You can also share your feedback on Copilot code review. Take the survey.
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 6 out of 6 changed files in this pull request and generated 2 comments.
You can also share your feedback on Copilot code review. Take the survey.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.
You can also share your feedback on Copilot code review. Take the survey.
|
|
||
| @dataclass(frozen=True) | ||
| class LocalDbRestoreResult: | ||
| sql_file: Path |
There was a problem hiding this comment.
LocalDbRestoreResult declares a required sql_file: Path, but restore_local_db_from_sql() never populates it. As written this will raise a TypeError at runtime when constructing the dataclass, breaking the CLI and tests. Either remove sql_file from the result type, or make it optional / define what it should represent (note the staged file is in a TemporaryDirectory and will not exist after the context exits).
| sql_file: Path |
| host=host, | ||
| port=port, | ||
| user=user, | ||
| db_name=target_db, |
There was a problem hiding this comment.
This LocalDbRestoreResult(...) construction is missing the required sql_file field from the dataclass definition, which will raise TypeError: __init__() missing 1 required positional argument at runtime. Pass a value for sql_file (and ensure it points to a stable path), or adjust the dataclass fields to match what the function can safely return.
| db_name=target_db, | |
| db_name=target_db, | |
| sql_file=staged_sql_file, |
| try: | ||
| _reset_target_schema() | ||
| except LocalDbRestoreError: | ||
| raise | ||
| except Exception as exc: | ||
| raise LocalDbRestoreError( | ||
| f"Failed to reset the public schema before restore: {exc}" | ||
| ) from exc |
There was a problem hiding this comment.
The try/except around _reset_target_schema() is redundant because _reset_target_schema() already catches all exceptions and re-raises LocalDbRestoreError. Consider removing this extra wrapper to avoid duplicated error formatting and keep the control flow simpler.
| try: | |
| _reset_target_schema() | |
| except LocalDbRestoreError: | |
| raise | |
| except Exception as exc: | |
| raise LocalDbRestoreError( | |
| f"Failed to reset the public schema before restore: {exc}" | |
| ) from exc | |
| _reset_target_schema() |
Why
This PR addresses the following problem / context:
How
Implementation summary - the following was changed / added / removed:
Notes
Any special considerations, workarounds, or follow-up work to note?