Exception Hierarchy & Error Handling
Relevant source files
The following files were used as context for generating this wiki page:
Introduction
The FLEXT DB Oracle library implements a structured approach to error management, primarily utilizing a dedicated exception hierarchy and Railway-Oriented Programming (ROP) patterns. The exception system is designed to provide enterprise-grade reliability by categorizing Oracle-specific errors, such as connection failures and DDL generation issues, into a manageable class hierarchy located in the Foundation Layer of the architecture.
Beyond standard exceptions, the project integrates with FLEXT Core patterns, specifically the r[T] (Result) pattern. This approach ensures that operations across the Core Application Layer and Infrastructure Layer return result objects that explicitly indicate success or failure, reducing the need for aggressive try-catch blocks in business logic.
Sources: src/README.md:27-35, src/README.md:60-64, tests/unit/test_exceptions.py:17-43
Exception Architecture
The library defines a custom exception hierarchy tailored for Oracle database operations. All custom exceptions reside in the flext_db_oracle.exceptions module and serve as the standard mechanism for signaling fatal failures that cannot be handled via functional result patterns.
The e Namespace
Custom exceptions are organized under the e alias within the exceptions.py module. This provides a clean interface for raising and catching library-specific errors.
| Exception Class | Purpose |
|---|---|
Error | Base class for all library-specific exceptions. Supports optional oracle_error_code. |
OracleConnectionError | Specifically raised for failures during the connection lifecycle or resource management. |
Sources: src/flext_db_oracle/exceptions.py:1-15, tests/unit/test_exceptions.py:17-43
Exception Hierarchy Diagram
The following diagram illustrates the relationship between the base error class and specialized exception types.
The hierarchy ensures that users can catch specialized errors like OracleConnectionError or catch the broader Error for general database logic failures.
Sources: tests/unit/test_exceptions.py:17-43
Railway-Oriented Programming (r[T])
A significant portion of the library's error handling is performed using the r[T] (Result) pattern from FLEXT Core. Instead of raising exceptions for every failure, methods in the FlextDbOracleApi and FlextDbOracleServices return a Result object that contains either the successful value or a descriptive error string.
Pattern Implementation
When an operation like test_connection() or query() is executed, the return value is evaluated for its success or failure state.
Result Usage Examples
The r[T] pattern is extensively used for:
- Connection Testing: Verifying database reachability without crashing the application.
- SQL Building: Handling invalid identifiers or empty column lists during DDL generation.
- Metadata Extraction: Returning failures when schema introspection fails due to missing permissions or connectivity.
Sources: src/README.md:60-64, tests/unit/test_services.py:48-52, tests/unit/test_services.py:461-465, tests/unit/test_api.py:133-145
Error Scenarios and Logic
Connection Failures
Connection errors are handled through both the exception hierarchy (for fatal infrastructure issues) and the Result pattern (for runtime validation). The library validates host, port, and credentials before attempting connection.
| Scenario | Handling Mechanism | Expected Output/Behavior |
|---|---|---|
| Invalid Configuration | Result Object | .failure = True, .error contains validation message |
| Database Timeout | Result Object | .failure = True, .error contains "connection" or "timeout" |
| Fatal Resource Exhaustion | OracleConnectionError | Exception raised to caller |
Sources: tests/unit/test_api.py:192-205, tests/unit/test_services.py:615-635
SQL Generation Errors
The library includes defensive logic in its SQL builders to prevent invalid DDL generation. For example, methods like build_create_index_statement return a failed result if required parameters are missing.
def test_build_create_index_statement_fails_for_empty_columns(self) -> None:
service = self._make_service()
result = service.build_create_index_statement({
"table_name": "USERS",
"index_name": "IDX_USERS_EMPTY",
"columns": [],
})
tm.that(result.failure, eq=True)
tm.that((result.error or ""), has="at least one column")
Sources: tests/unit/test_services.py:461-470
Conclusion
The FLEXT DB Oracle library ensures robust operation through a dual-layered error handling strategy. By combining a traditional Python exception hierarchy in flext_db_oracle.exceptions for fatal errors with the Railway-Oriented r[T] pattern for functional failures, the library provides developers with precise control over error states. This architecture is crucial for maintaining stability in enterprise environments where database connectivity and metadata integrity are paramount.
Sources: src/README.md:27-35, src/README.md:60-64, tests/README.md:225-240