Add DB inspection and pg_trgm utility scripts#43
Conversation
Add four small database utility scripts under app/api/prospects/database: - check_chris.py: searches prospects for occurrences of "chris" in first_name, last_name, email, or company_name (limits output). - check_pg_trgm.py: checks whether the pg_trgm extension is installed. - enable_pg_trgm.py: enables the pg_trgm extension (intended to be run once/migration-like). - print_prospects_columns.py: prints column names from the prospects table for debugging. All scripts use get_db_connection from app.utils.db and include simple error handling and CLI entry points where appropriate.
There was a problem hiding this comment.
Pull request overview
Adds a small set of PostgreSQL/prospects database utility scripts under app/api/prospects/database to help with one-off DB inspection and managing the pg_trgm extension.
Changes:
- Add a script to print column names for the
prospectstable. - Add scripts to check for and enable the
pg_trgmextension. - Add a quick script to find prospects containing “chris” in selected fields.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 10 comments.
| File | Description |
|---|---|
| app/api/prospects/database/print_prospects_columns.py | Prints prospects table column names by querying a sample row. |
| app/api/prospects/database/enable_pg_trgm.py | Enables pg_trgm via CREATE EXTENSION IF NOT EXISTS .... |
| app/api/prospects/database/check_pg_trgm.py | Checks whether pg_trgm is installed via pg_extension. |
| app/api/prospects/database/check_chris.py | Searches for “chris” across selected prospects fields (limited output). |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| def check_chris(): | ||
|
|
||
| from app.utils.db import get_db_connection | ||
|
|
There was a problem hiding this comment.
The module currently has an empty def check_chris(): followed by a second def check_chris(): and a top-level import after the first function header. As written, this is a syntax/indentation error (function with no body) and the script will fail to run/import. Remove the stray first definition and move imports to the top so there is exactly one valid check_chris function definition.
| def check_chris(): | |
| from app.utils.db import get_db_connection | |
| from app.utils.db import get_db_connection |
| print(f"Error: {e}") | ||
| finally: | ||
| cur.close() | ||
| conn.close() | ||
|
|
There was a problem hiding this comment.
PR description mentions these scripts include CLI entry points where appropriate, but this script doesn't currently have an if __name__ == "__main__": ... block to invoke check_chris(). Add a main guard at the bottom so it can be run directly like the other utility scripts.
| Migration script to enable pg_trgm extension for fuzzy search support. | ||
| Run this script once to enable the extension in your PostgreSQL database. | ||
| """ | ||
| import psycopg2 |
There was a problem hiding this comment.
psycopg2 is imported but never used in this script. Removing the unused import avoids lint failures and reduces confusion about intended exception handling.
| import psycopg2 |
| cur.execute("CREATE EXTENSION IF NOT EXISTS pg_trgm;") | ||
| conn.commit() | ||
| print("pg_trgm extension enabled successfully.") | ||
| except Exception as e: |
There was a problem hiding this comment.
On exception, the connection is left in a failed transaction state but never rolled back. Add conn.rollback() in the except block so the connection is cleanly reset before closing (and to match error-handling patterns used in other DB scripts/endpoints).
| except Exception as e: | |
| except Exception as e: | |
| conn.rollback() |
| """ | ||
| Check if pg_trgm extension is enabled in the PostgreSQL database. | ||
| """ | ||
| import psycopg2 |
There was a problem hiding this comment.
psycopg2 is imported but not used anywhere in this script. Please remove the unused import to avoid lint errors and keep dependencies clear.
| import psycopg2 |
| from app.utils.db import get_db_connection | ||
|
|
||
| def check_pg_trgm(): | ||
| conn_gen = get_db_connection() | ||
| conn = next(conn_gen) |
There was a problem hiding this comment.
get_db_connection() is a generator intended for FastAPI dependency injection (it closes the connection in the generator's finally). Here the generator is advanced with next() but never closed, so that finally block will not run. Prefer get_db_connection_direct() for scripts, or explicitly close the generator (e.g., in finally) instead of only closing the connection.
| from app.utils.db import get_db_connection | |
| def check_pg_trgm(): | |
| conn_gen = get_db_connection() | |
| conn = next(conn_gen) | |
| from app.utils.db import get_db_connection_direct | |
| def check_pg_trgm(): | |
| conn = get_db_connection_direct() |
| from app.utils.db import get_db_connection | ||
|
|
||
| def enable_pg_trgm(): | ||
| conn_gen = get_db_connection() | ||
| conn = next(conn_gen) |
There was a problem hiding this comment.
get_db_connection() is a generator meant to be used as a FastAPI dependency; advancing it with next() without later closing the generator skips its finally cleanup path. For standalone scripts, prefer get_db_connection_direct(), or ensure the generator is properly closed in finally (rather than only calling conn.close()).
| from app.utils.db import get_db_connection | |
| def enable_pg_trgm(): | |
| conn_gen = get_db_connection() | |
| conn = next(conn_gen) | |
| from app.utils.db import get_db_connection, get_db_connection_direct | |
| def enable_pg_trgm(): | |
| conn = get_db_connection_direct() |
| conn = next(conn_gen) | ||
| cur = conn.cursor() | ||
| try: | ||
| cur.execute("SELECT * FROM prospects LIMIT 1;") | ||
| columns = [desc[0] for desc in cur.description] | ||
| print("Columns in prospects table:", columns) | ||
| except Exception as e: | ||
| print(f"Error: {e}") | ||
| finally: | ||
| cur.close() | ||
| conn.close() |
There was a problem hiding this comment.
get_db_connection() is implemented as a generator (FastAPI dependency). This script calls next() on it but never closes the generator, so the generator's finally block is skipped. Use get_db_connection_direct() for one-off scripts, or close the generator in finally to ensure its cleanup logic always runs.
| conn = next(conn_gen) | |
| cur = conn.cursor() | |
| try: | |
| cur.execute("SELECT * FROM prospects LIMIT 1;") | |
| columns = [desc[0] for desc in cur.description] | |
| print("Columns in prospects table:", columns) | |
| except Exception as e: | |
| print(f"Error: {e}") | |
| finally: | |
| cur.close() | |
| conn.close() | |
| try: | |
| conn = next(conn_gen) | |
| cur = conn.cursor() | |
| try: | |
| cur.execute("SELECT * FROM prospects LIMIT 1;") | |
| columns = [desc[0] for desc in cur.description] | |
| print("Columns in prospects table:", columns) | |
| except Exception as e: | |
| print(f"Error: {e}") | |
| finally: | |
| cur.close() | |
| conn.close() | |
| finally: | |
| conn_gen.close() |
| except Exception as e: | ||
| print(f"Error: {e}") | ||
| finally: | ||
| cur.close() | ||
| conn.close() |
There was a problem hiding this comment.
If the SELECT fails (e.g., missing table/permissions), psycopg2 leaves the session in an aborted transaction state. Consider calling conn.rollback() in the except block to keep error handling consistent with the other DB utility scripts in this directory.
| from app.utils.db import get_db_connection | ||
|
|
||
| def check_chris(): | ||
| conn_gen = get_db_connection() | ||
| conn = next(conn_gen) |
There was a problem hiding this comment.
Same as the other scripts: get_db_connection() is a generator with cleanup in its finally, but this script advances it with next() and never closes the generator. Prefer get_db_connection_direct() for this standalone script, or close the generator explicitly in finally to ensure the generator's cleanup path runs.
| from app.utils.db import get_db_connection | |
| def check_chris(): | |
| conn_gen = get_db_connection() | |
| conn = next(conn_gen) | |
| from app.utils.db import get_db_connection_direct | |
| def check_chris(): | |
| conn = get_db_connection_direct() |
Add four small database utility scripts under app/api/prospects/database:
All scripts use get_db_connection from app.utils.db and include simple error handling and CLI entry points where appropriate.