EXECUTION_PIPELINE.md¶
RowGuard Execution Pipeline¶
Purpose¶
This document specifies the end-to-end execution pipeline used by RowGuard. The pipeline is deterministic: the same execution plan, database state, and configuration should always produce the same outcome.
The pipeline separates planning from execution so each stage is independently testable and replaceable.
High-Level Flow¶
Application
│
▼
Execution Plan
│
▼
Query Builder
│
▼
SQLRules Filter Pushdown
│
▼
SQLAlchemy Statement
│
▼
Database Execution
│
▼
Row Adapter
│
▼
Pydantic Validation
│
├── Valid Model
└── Validation Failure
│
▼
Reject Handler
│
▼
Result Assembler
│
▼
QueryResult
Stage 1 – Build Execution Plan¶
Inputs:
Session or AsyncSession
SQLAlchemy table, selectable, or statement
Pydantic model
Rejection policy
Diagnostics options
Streaming configuration
Output:
An immutable ExecutionPlan.
No database access occurs during this stage.
Stage 2 – Query Construction¶
If the caller supplied a table or ORM model, RowGuard constructs a
SQLAlchemy Select statement.
If a statement was supplied, this stage simply validates it.
Stage 3 – SQLRules Integration¶
When enabled, RowGuard invokes SQLRules to compile SQL-safe constraints from the Pydantic model into SQLAlchemy expressions.
These expressions are merged into the statement’s WHERE clause.
This stage performs no database I/O.
Stage 4 – Execute Statement¶
The Query Engine executes the SQLAlchemy statement using the supplied session.
Execution modes:
Buffered
Streaming
Execution errors are surfaced immediately.
Stage 5 – Adapt Rows¶
Each SQLAlchemy row is converted into a mapping suitable for Pydantic.
Responsibilities include:
Preserve column names
Respect aliases
Handle duplicate columns
Produce deterministic mappings
Output:
dict[str, object]
Stage 6 – Validate¶
Each mapping is validated using:
Model.model_validate(mapping)
Possible outcomes:
Valid model
ValidationError
Validation is performed one row at a time.
Stage 7 – Handle Rejections¶
Validation failures are forwarded to the configured rejection policy.
Supported policies:
raise
collect
skip
log
callback
quarantine
No validation failure should disappear silently.
Stage 8 – Collect Statistics¶
The pipeline records:
rows read
rows validated
rows accepted
rows rejected
execution time
validation time
Future metrics may include throughput and adaptation time.
Stage 9 – Assemble Result¶
Buffered execution returns:
QueryResult[T]
containing:
models
rejected rows
statistics
diagnostics
executed statement
Streaming execution yields validated models incrementally while maintaining optional statistics.
Error Propagation¶
Pipeline stages should fail with contextual exceptions.
Expected public errors include:
QueryExecutionError
ValidationFailure
RejectHandlerError
ConfigurationError
Unexpected failures are wrapped with execution context.
Pipeline Invariants¶
The execution pipeline must guarantee:
Every processed row is classified.
Accepted rows satisfy the target Pydantic model.
Rejected rows are observable.
Stage ordering never changes.
Statistics reflect actual processing.
Extensibility¶
Future plugins may participate in:
execution observers
row adaptation
rejection handling
diagnostics
metrics
tracing
Extension points should not alter the core stage ordering.
Design Principles¶
Immutable execution plans
One responsibility per stage
Explicit state transitions
Deterministic execution
SQLAlchemy-native behavior
Pydantic-driven validation