The class metaobject called persistent-class in cl-perec extends the CLOS standard-class and allows classes to have persistent slots. In fact defpclass is nothing more than a defclass with a (:metaclass persistent-class). In a persistent class all slots are persistent by default unless the :persistent nil slot option is specified in which case the slot will be a standard slot. The persistent-class implements a subset of the CL type system and maps slots to RDBMS tables and columns. For several primitive types this can be done efficiently while some CL types need to be serialized and stored as BLOB in the RDBMS.
The intention of cl-perec is to completely hide the RDBMS part from the user. It creates and alters tables automatically (signals continuable errors for schema changes) so the user can mostly think in CLOS terms.
There is another class metaobject called persistent-association which allows two slots in two different classes to be in referential integrity. There are three different kind of associations: one-to-one, one-to-many and many-to-many. The many association end means an unordered set of persistent objects.
Another nice part is the query compiler which provides a convenient way to express queries in the lisp type system which is then mapped to efficient SQL queries if possible. Even if the entire query cannot be mapped to a single SQL statement, parts of it will transparently be run in the Lisp VM. Ordering, slot accessors, literals and lisp predicates can be used to build the query, see the huge number of tests for more details.
The persistent type system supports a subset of the Common Lisp type system, type aliasing and subtyping are transparently mapped to RDBMS. New primitive persistent types can be defined with defptype and defmapping. The extended metaobject protocol allows mapping lisp types to multiple RDBMS columns (e.g. the type (or null unbound integer) needs two columns).