-
Notifications
You must be signed in to change notification settings - Fork 6
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
return exceptions on Execute commands for postgresql (asyncpg driver) #1320
Conversation
Reviewer's Guide by SourceryThis PR enhances error handling in the PostgreSQL (asyncpg) driver by adding specific exception handling for common database errors. The changes affect the execute methods in both the main driver and cursor implementations, ensuring that certain database-specific errors are logged and re-raised rather than being wrapped in a generic ProviderError. Updated class diagram for asyncpg driver error handlingclassDiagram
class AsyncPgDriver {
+execute(sentence, *args)
+execute_many(sentence, *args)
}
class pgCursor {
+execute(sentence, *args, **kwargs)
+execute_many(sentence, *args)
}
class QueryCanceledError
class StatementError
class UniqueViolationError
class ForeignKeyViolationError
class NotNullViolationError
class InvalidSQLStatementNameError
class PostgresSyntaxError
class UndefinedColumnError
class UndefinedTableError
class DuplicateTableError
class PostgresError
class InterfaceError
class ProviderError
class InterfaceWarning
AsyncPgDriver --> QueryCanceledError
AsyncPgDriver --> StatementError
AsyncPgDriver --> UniqueViolationError
AsyncPgDriver --> ForeignKeyViolationError
AsyncPgDriver --> NotNullViolationError
AsyncPgDriver --> InterfaceError
AsyncPgDriver --> ProviderError
pgCursor --> QueryCanceledError
pgCursor --> StatementError
pgCursor --> UniqueViolationError
pgCursor --> ForeignKeyViolationError
pgCursor --> NotNullViolationError
pgCursor --> InvalidSQLStatementNameError
pgCursor --> PostgresSyntaxError
pgCursor --> UndefinedColumnError
pgCursor --> UndefinedTableError
pgCursor --> DuplicateTableError
pgCursor --> PostgresError
pgCursor --> InterfaceWarning
pgCursor --> ProviderError
note for AsyncPgDriver "Handles specific database errors and logs them"
note for pgCursor "Handles specific database errors and logs them"
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey @phenobarbital - I've reviewed your changes - here's some feedback:
Overall Comments:
- Consider extracting the common exception tuple (QueryCanceledError, StatementError, etc.) into a module-level constant to avoid repetition and make future maintenance easier.
Here's what I looked at during the review
- 🟢 General issues: all looks good
- 🟢 Security: all looks good
- 🟢 Testing: all looks good
- 🟡 Complexity: 1 issue found
- 🟢 Documentation: all looks good
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
@@ -414,10 +417,25 @@ async def execute(self, sentence, *args): | |||
""" | |||
try: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
issue (complexity): Consider extracting duplicated error handling logic into a reusable decorator function
The error handling logic is duplicated across execute(), execute_many() and the pool's execute(). Consider extracting this into a decorator:
def handle_pg_errors(f):
async def wrapper(*args, **kwargs):
try:
return await f(*args, **kwargs)
except (
QueryCanceledError,
StatementError,
UniqueViolationError,
ForeignKeyViolationError,
NotNullViolationError
) as err:
self._logger.warning(f"AsyncPg: {err}")
raise
except (
InvalidSQLStatementNameError,
PostgresSyntaxError,
UndefinedColumnError,
UndefinedTableError
) as err:
return await self._serializer(None, err)
except Exception as err:
return await self._serializer(None, f"Error: {err}")
return wrapper
@handle_pg_errors
async def execute(self, sentence, *args, **kwargs):
self.start_timing()
await self.valid_operation(sentence)
self._result = await self._connection.execute(sentence, *args, **kwargs)
self.generated_at()
return await self._serializer(self._result, None)
This maintains the improved error handling while eliminating duplication. The decorator can be reused across all execute methods.
Summary by Sourcery
Improve error handling in the asyncpg driver by returning specific exceptions for execute commands and logging warnings for these exceptions. Update the library version to 2.9.4.
Bug Fixes:
Enhancements:
Chores: