Using the SQLAlchemy ORM, I want to make sure values are the right type for their columns.
For example, say I have an Integer column. I try to insert the value “hello”, which is not a valid integer. SQLAlchemy will allow me to do this. Only later, when I execute session.commit(), does it raise an exception: sqlalchemy.exc.DataError: (DataError) invalid input syntax integer: "hello"….
I am adding batches of records, and I don’t want to commit after every single add(…), for performance reasons.
So how can I:
- Raise the exception as soon as I do
session.add(…) - Or, make sure the value I am inserting can be converted to the target Column datatype, before adding it to the batch?
- Or any other way to prevent one bad record from spoiling an entire
commit().
SQLAlchemy doesn’t build this in as it defers to the DBAPI/database as the best and most efficient source of validation and coercion of values.
To build your own validation, usually TypeDecorator or ORM-level validation is used. TypeDecorator has the advantage that it operates at the core and can be pretty transparent, though it only occurs when SQL is actually emitted.
To do validation and coercion sooner, this is at the ORM level.
Validation can be ad-hoc, at the ORM layer, via
@validates:http://docs.sqlalchemy.org/en/latest/orm/mapped_attributes.html#simple-validators
The event system that @validates uses is also available directly. You can write a generalized solution that links validators of your choosing to the types being mapped:
Validation and coercion can also be built at the type level using TypeDecorator, though this is only when SQL is being emitted, such as this example which coerces utf-8 strings to unicode:
http://docs.sqlalchemy.org/en/latest/core/custom_types.html#coercing-encoded-strings-to-unicode