    {-# LANGUAGE ConstraintKinds #-}

    -- | This module exports all of the type classes in @persistent@ for operating
    -- on the database backends.
    --
    -- @persistent@ offers methods that are abstract in the specific @backend@ type.
    -- For SQL databases, this wil be 'Database.Persist.SqlBackend.SqlBackend'.
    -- Other database backends will define their own types.
    --
    -- Methods and functions in this module have examples documented under an
    -- "Example Usage" thing, that you need to click on to expand.
    --
    module Database.Persist.Class
        (

        -- * PersistStore
        -- | The 'PersistStore', 'PersistStoreRead', and 'PersistStoreWrite' type
        -- classes are used to define basic operations on the database. A database
        -- that implements these classes is capable of being used as a simple
        -- key-value store.
        --
        -- All the examples present here will be explained based on these schemas, datasets and functions:
        --
        -- = schema-1
        --
        -- #schema-persist-store-1#
        --
        -- > share [mkPersist sqlSettings, mkMigrate "migrateAll"] [persistLowerCase|
        -- > User
        -- >     name String
        -- >     age Int
        -- >     deriving Show
        -- > |]
        --
        -- = dataset-1
        --
        -- #dataset-persist-store-1#
        --
        -- > +----+-------+-----+
        -- > | id | name  | age |
        -- > +----+-------+-----+
        -- > |  1 | SPJ   |  40 |
        -- > +----+-------+-----+
        -- > |  2 | Simon |  41 |
        -- > +----+-------+-----+
          PersistStore
        , PersistStoreRead (..)
        , PersistStoreWrite (..)
        , PersistRecordBackend
        , getJust
        , getJustEntity
        , getEntity
        , belongsTo
        , belongsToJust
        , SafeToInsert
        , insertEntity
        , insertRecord

        -- * PersistUnique
        -- | The 'PersistUnique' type class is relevant for database backends that
        -- offer uniqueness keys. Uniquenes keys allow us to perform operations like
        -- 'getBy', 'deleteBy', as well as 'upsert' and 'putMany'.
        --
        -- All the examples present here will be explained based on these two schemas and the dataset:
        --
        -- = schema-1
        -- This schema has single unique constraint.
        --
        -- #schema-persist-unique-1#
        --
        -- > share [mkPersist sqlSettings, mkMigrate "migrateAll"] [persistLowerCase|
        -- > User
        -- >     name String
        -- >     age Int
        -- >     UniqueUserName name
        -- >     deriving Show
        -- > |]
        --
        -- = schema-2
        -- This schema has two unique constraints.
        --
        -- #schema-persist-unique-2#
        --
        -- > share [mkPersist sqlSettings, mkMigrate "migrateAll"] [persistLowerCase|
        -- > User
        -- >     name String
        -- >     age Int
        -- >     UniqueUserName name
        -- >     UniqueUserAge age
        -- >     deriving Show
        -- > |]
        --
        -- = dataset-1
        --
        -- #dataset-persist-unique-1#
        --
        -- > +-----+-----+-----+
        -- > |id   |name |age  |
        -- > +-----+-----+-----+
        -- > |1    |SPJ  |40   |
        -- > +-----+-----+-----+
        -- > |2    |Simon|41   |
        -- > +-----+-----+-----+

        , PersistUnique
        , PersistUniqueRead (..)
        , PersistUniqueWrite (..)
        , OnlyOneUniqueKey (..)
        , AtLeastOneUniqueKey (..)
        , onlyOneUniqueDef
        , NoUniqueKeysError
        , MultipleUniqueKeysError
        , getByValue
        , insertBy
        , insertUniqueEntity
        , replaceUnique
        , checkUnique
        , checkUniqueUpdateable
        , onlyUnique

        -- * PersistQuery
        -- |  The 'PersistQuery' type class allows us to select lists and filter
        -- database models.  'selectList' is the canonical read operation, and we
        -- can write 'updateWhere' and 'deleteWhere' to modify based on filters.
        , selectList
        , selectKeys
        , PersistQuery
        , PersistQueryRead (..)
        , PersistQueryWrite (..)
        , selectSource
        , selectKeysList

        -- * PersistEntity
        , PersistEntity (..)
        , tabulateEntity
        , SymbolToField (..)
        -- * PersistField
        , PersistField (..)
        -- * PersistConfig
        , PersistConfig (..)
        , entityValues

        -- * Lifting
        , HasPersistBackend (..)
        , withBaseBackend
        , IsPersistBackend ()
        , liftPersist
        , BackendCompatible (..)
        , withCompatibleBackend

        -- * PersistCore
        -- | 'PersistCore' is a type class that defines a default database
        -- 'BackendKey' type. For SQL databases, this is currently an
        -- auto-incrementing inteer primary key. For MongoDB, it is the default
        -- ObjectID.
        , PersistCore (..)
        , ToBackendKey (..)
        -- * JSON utilities
        , keyValueEntityToJSON, keyValueEntityFromJSON
        , entityIdToJSON, entityIdFromJSON
        , toPersistValueJSON, fromPersistValueJSON
        ) where

    import Database.Persist.Class.PersistConfig
    import Database.Persist.Class.PersistEntity
    import Database.Persist.Class.PersistField
    import Database.Persist.Class.PersistQuery
    import Database.Persist.Class.PersistStore
    import Database.Persist.Class.PersistUnique

    -- | A backwards-compatible alias for those that don't care about distinguishing between read and write queries.
    -- It signifies the assumption that, by default, a backend can write as well as read.
    type PersistUnique a = PersistUniqueWrite a

    -- | A backwards-compatible alias for those that don't care about distinguishing between read and write queries.
    -- It signifies the assumption that, by default, a backend can write as well as read.
    type PersistQuery a = PersistQueryWrite a

    -- | A backwards-compatible alias for those that don't care about distinguishing between read and write queries.
    -- It signifies the assumption that, by default, a backend can write as well as read.
    type PersistStore a = PersistStoreWrite a