packages feed

persistent 2.13.1.1 → 2.13.1.2

raw patch · 11 files changed

+845/−148 lines, 11 filesPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

API changes (from Hackage documentation)

- Database.Persist.Sql: PersistUnsafeMigrationException :: [(Bool, Sql)] -> PersistUnsafeMigrationException
- Database.Persist.Sql: addMigration :: Bool -> Sql -> Migration
- Database.Persist.Sql: addMigrations :: CautiousMigration -> Migration
- Database.Persist.Sql: getMigration :: (MonadIO m, HasCallStack) => Migration -> ReaderT SqlBackend m [Sql]
- Database.Persist.Sql: migrate :: [EntityDef] -> EntityDef -> Migration
- Database.Persist.Sql: newtype PersistUnsafeMigrationException
- Database.Persist.Sql: parseMigration :: (HasCallStack, MonadIO m) => Migration -> ReaderT SqlBackend m (Either [Text] CautiousMigration)
- Database.Persist.Sql: parseMigration' :: (HasCallStack, MonadIO m) => Migration -> ReaderT SqlBackend m CautiousMigration
- Database.Persist.Sql: printMigration :: (HasCallStack, MonadIO m) => Migration -> ReaderT SqlBackend m ()
- Database.Persist.Sql: reportError :: Text -> Migration
- Database.Persist.Sql: reportErrors :: [Text] -> Migration
- Database.Persist.Sql: runMigration :: MonadIO m => Migration -> ReaderT SqlBackend m ()
- Database.Persist.Sql: runMigrationQuiet :: MonadIO m => Migration -> ReaderT SqlBackend m [Text]
- Database.Persist.Sql: runMigrationSilent :: MonadUnliftIO m => Migration -> ReaderT SqlBackend m [Text]
- Database.Persist.Sql: runMigrationUnsafe :: MonadIO m => Migration -> ReaderT SqlBackend m ()
- Database.Persist.Sql: runMigrationUnsafeQuiet :: (HasCallStack, MonadIO m) => Migration -> ReaderT SqlBackend m [Text]
- Database.Persist.Sql: runSqlCommand :: SqlPersistT IO () -> Migration
- Database.Persist.Sql: showMigration :: (HasCallStack, MonadIO m) => Migration -> ReaderT SqlBackend m [Text]
- Database.Persist.Sql: type CautiousMigration = [(Bool, Sql)]
- Database.Persist.Sql: type Migration = WriterT [Text] (WriterT CautiousMigration (ReaderT SqlBackend IO)) ()
- Database.Persist.Sql: type Sql = Text
+ Database.Persist.Sql.Migration: PersistUnsafeMigrationException :: [(Bool, Sql)] -> PersistUnsafeMigrationException
+ Database.Persist.Sql.Migration: addMigration :: Bool -> Sql -> Migration
+ Database.Persist.Sql.Migration: addMigrations :: CautiousMigration -> Migration
+ Database.Persist.Sql.Migration: getMigration :: (MonadIO m, HasCallStack) => Migration -> ReaderT SqlBackend m [Sql]
+ Database.Persist.Sql.Migration: instance GHC.Exception.Type.Exception Database.Persist.Sql.Migration.PersistUnsafeMigrationException
+ Database.Persist.Sql.Migration: instance GHC.Show.Show Database.Persist.Sql.Migration.PersistUnsafeMigrationException
+ Database.Persist.Sql.Migration: migrate :: [EntityDef] -> EntityDef -> Migration
+ Database.Persist.Sql.Migration: newtype PersistUnsafeMigrationException
+ Database.Persist.Sql.Migration: parseMigration :: (HasCallStack, MonadIO m) => Migration -> ReaderT SqlBackend m (Either [Text] CautiousMigration)
+ Database.Persist.Sql.Migration: parseMigration' :: (HasCallStack, MonadIO m) => Migration -> ReaderT SqlBackend m CautiousMigration
+ Database.Persist.Sql.Migration: printMigration :: (HasCallStack, MonadIO m) => Migration -> ReaderT SqlBackend m ()
+ Database.Persist.Sql.Migration: reportError :: Text -> Migration
+ Database.Persist.Sql.Migration: reportErrors :: [Text] -> Migration
+ Database.Persist.Sql.Migration: runMigration :: MonadIO m => Migration -> ReaderT SqlBackend m ()
+ Database.Persist.Sql.Migration: runMigrationQuiet :: MonadIO m => Migration -> ReaderT SqlBackend m [Text]
+ Database.Persist.Sql.Migration: runMigrationSilent :: MonadUnliftIO m => Migration -> ReaderT SqlBackend m [Text]
+ Database.Persist.Sql.Migration: runMigrationUnsafe :: MonadIO m => Migration -> ReaderT SqlBackend m ()
+ Database.Persist.Sql.Migration: runMigrationUnsafeQuiet :: (HasCallStack, MonadIO m) => Migration -> ReaderT SqlBackend m [Text]
+ Database.Persist.Sql.Migration: runSqlCommand :: SqlPersistT IO () -> Migration
+ Database.Persist.Sql.Migration: showMigration :: (HasCallStack, MonadIO m) => Migration -> ReaderT SqlBackend m [Text]
+ Database.Persist.Sql.Migration: type CautiousMigration = [(Bool, Sql)]
+ Database.Persist.Sql.Migration: type Migration = WriterT [Text] (WriterT CautiousMigration (ReaderT SqlBackend IO)) ()
+ Database.Persist.Sql.Migration: type Sql = Text
- Database.Persist.Class: data family Unique record;
+ Database.Persist.Class: data family BackendKey backend;
- Database.Persist.Sql.Util: keyAndEntityColumnNames :: EntityDef -> SqlBackend -> NonEmpty Sql
+ Database.Persist.Sql.Util: keyAndEntityColumnNames :: EntityDef -> SqlBackend -> NonEmpty Text

Files

ChangeLog.md view
@@ -1,5 +1,14 @@ # Changelog for persistent +## 2.13.1.2++* [#1308](https://github.com/yesodweb/persistent/pull/1308)+    * Consolidate the documentation for the Persistent quasiquoter in+      Database.Persist.Quasi.+* [#1312](https://github.com/yesodweb/persistent/pull/1312)+    * Reorganize documentation and link to more modules.+    * Expose `Database.Persist.Sql.Migration`+ ## 2.13.1.1  * [#1294](https://github.com/yesodweb/persistent/pull/1294)
Database/Persist.hs view
@@ -1,37 +1,91 @@ {-# LANGUAGE ExistentialQuantification #-} +-- | Welcome to @persistent@!+--+-- This library intends to provide an easy, flexible, and convenient interface+-- to various data storage backends. Backends include SQL databases, like+-- @mysql@, @postgresql@, and @sqlite@, as well as NoSQL databases, like+-- @mongodb@ and @redis@.+--+-- If you intend on using a SQL database, then check out "Database.Persist.Sql". module Database.Persist-    ( module Database.Persist.Class+    (+-- * Defining Database Models+--+-- | @persistent@ lets you define your database models using a special syntax.+-- This syntax allows you to customize the resulting Haskell datatypes and+-- database schema. See "Database.Persist.Quasi" for details on that definition+-- language.+--+-- ** Reference Schema & Dataset+--+-- | For a quick example of the syntax, we'll introduce this database schema, and+-- we'll use it to explain the update and filter combinators.+--+-- @+-- 'share' ['mkPersist' 'sqlSettings', 'mkMigrate' "migrateAll"] ['persistLowerCase'|+-- User+--     name String+--     age Int+--     deriving Show+-- |]+-- @+--+-- This creates a Haskell datatpe that looks like this:+--+-- @+-- data User = User+--     { userName :: String+--     , userAge :: Int+--     }+--     deriving Show+-- @+--+-- In a SQL database, we'd get a migration like this:+--+-- @+-- CREATE TABLE "user" (+--      id    SERIAL PRIMARY KEY,+--      name  TEXT NOT NULL,+--      age   INT NOT NULL+-- );+-- @+--+-- The examples below will refer to this as dataset-1.+--+-- #dataset#+--+-- > +-----+-----+-----++-- > |id   |name |age  |+-- > +-----+-----+-----++-- > |1    |SPJ  |40   |+-- > +-----+-----+-----++-- > |2    |Simon|41   |+-- > +-----+-----+-----+++        -- * Database Operations+      -- | The module "Database.Persist.Class" defines how to operate with+        -- @persistent@ database models. Check that module out for basic+        -- operations, like 'get', 'insert', and 'selectList'.+      module Database.Persist.Class+      -- * Types+      -- | This module re-export contains a lot of the important types for+      -- working with @persistent@ datatypes and underlying values.     , module Database.Persist.Types -    -- * Reference Schema & Dataset-    -- |-    ---    -- All the combinators present here will be explained based on this schema:-    ---    -- > share [mkPersist sqlSettings, mkMigrate "migrateAll"] [persistLowerCase|-    -- > User-    -- >     name String-    -- >     age Int-    -- >     deriving Show-    -- > |]-    ---    -- and this dataset. The examples below will refer to this as dataset-1.-    ---    -- #dataset#-    ---    -- > +-----+-----+-----+-    -- > |id   |name |age  |-    -- > +-----+-----+-----+-    -- > |1    |SPJ  |40   |-    -- > +-----+-----+-----+-    -- > |2    |Simon|41   |-    -- > +-----+-----+-----++      -- * Query Operators+      -- | A convention that @persistent@ tries to follow is that operators on+      -- Database types correspond to a Haskell (or database) operator with a @.@+      -- character at the end. So to do @a || b@ , you'd write @a '||.' b@. To -    -- * Query update combinators+      -- ** Query update combinators+      -- | These operations are used when performing updates against the database.+      --  Functions like 'upsert' use them to provide new or modified values.     , (=.), (+=.), (-=.), (*=.), (/=.) -      -- * Query filter combinators+      -- ** Query filter combinators+      -- | These functions are useful in the 'PersistQuery' class, like+      -- 'selectList', 'updateWhere', etc.     , (==.), (!=.), (<.), (>.), (<=.), (>=.), (<-.), (/<-.), (||.)        -- * JSON Utilities@@ -60,7 +114,7 @@  -- | Assign a field a value. ----- === __Example usage__+-- === Examples -- -- @ -- updateAge :: MonadIO m => ReaderT SqlBackend m ()@@ -83,7 +137,7 @@  -- | Assign a field by addition (@+=@). ----- === __Example usage__+-- === Examples -- -- @ -- addAge :: MonadIO m => ReaderT SqlBackend m ()@@ -105,7 +159,7 @@  -- | Assign a field by subtraction (@-=@). ----- === __Example usage__+-- === Examples -- -- @ -- subtractAge :: MonadIO m => ReaderT SqlBackend m ()@@ -126,7 +180,7 @@  -- | Assign a field by multiplication (@*=@). ----- === __Example usage__+-- === Examples -- -- @ -- multiplyAge :: MonadIO m => ReaderT SqlBackend m ()@@ -148,7 +202,7 @@  -- | Assign a field by division (@/=@). ----- === __Example usage__+-- === Examples -- -- @ -- divideAge :: MonadIO m => ReaderT SqlBackend m ()@@ -173,7 +227,7 @@  -- | Check for equality. ----- === __Example usage__+-- === Examples -- -- @ -- selectSPJ :: MonadIO m => ReaderT SqlBackend m [Entity User]@@ -192,7 +246,7 @@  -- | Non-equality check. ----- === __Example usage__+-- === Examples -- -- @ -- selectSimon :: MonadIO m => ReaderT SqlBackend m [Entity User]@@ -211,7 +265,7 @@  -- | Less-than check. ----- === __Example usage__+-- === Examples -- -- @ -- selectLessAge :: MonadIO m => ReaderT SqlBackend m [Entity User]@@ -230,7 +284,7 @@  -- | Less-than or equal check. ----- === __Example usage__+-- === Examples -- -- @ -- selectLessEqualAge :: MonadIO m => ReaderT SqlBackend m [Entity User]@@ -249,7 +303,7 @@  -- | Greater-than check. ----- === __Example usage__+-- === Examples -- -- @ -- selectGreaterAge :: MonadIO m => ReaderT SqlBackend m [Entity User]@@ -268,7 +322,7 @@  -- | Greater-than or equal check. ----- === __Example usage__+-- === Examples -- -- @ -- selectGreaterEqualAge :: MonadIO m => ReaderT SqlBackend m [Entity User]@@ -290,7 +344,7 @@  -- | Check if value is in given list. ----- === __Example usage__+-- === Examples -- -- @ -- selectUsers :: MonadIO m => ReaderT SqlBackend m [Entity User]@@ -325,7 +379,7 @@  -- | Check if value is not in given list. ----- === __Example usage__+-- === Examples -- -- @ -- selectSimon :: MonadIO m => ReaderT SqlBackend m [Entity User]
Database/Persist/Class.hs view
@@ -1,9 +1,23 @@ {-# 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-    ( ToBackendKey (..)+    (      -- * 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:     --@@ -29,9 +43,7 @@     -- > +----+-------+-----+     -- > |  2 | Simon |  41 |     -- > +----+-------+-----+--    , PersistCore (..)-    , PersistStore+      PersistStore     , PersistStoreRead (..)     , PersistStoreWrite (..)     , PersistRecordBackend@@ -44,7 +56,9 @@     , 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:     --@@ -104,12 +118,15 @@     , 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-    , selectKeys-    , selectList     , selectKeysList      -- * DeleteCascade@@ -133,6 +150,13 @@     , 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
Database/Persist/Class/PersistQuery.hs view
@@ -1,10 +1,10 @@ {-# LANGUAGE ExplicitForAll #-} module Database.Persist.Class.PersistQuery-    ( PersistQueryRead (..)+    ( selectList+    , PersistQueryRead (..)     , PersistQueryWrite (..)     , selectSource     , selectKeys-    , selectList     , selectKeysList     ) where @@ -22,6 +22,12 @@ class (PersistCore backend, PersistStoreRead backend) => PersistQueryRead backend where     -- | Get all records matching the given criterion in the specified order.     -- Returns also the identifiers.+    --+    -- NOTE: This function returns an 'Acquire' and a 'ConduitM', which implies+    -- that it streams from the database. It does not. Please use 'selectList'+    -- to simplify the code. If you want streaming behavior, consider+    -- @persistent-pagination@ which efficiently chunks a query into ranges, or+    -- investigate a backend-specific streaming solution.     selectSourceRes            :: (PersistRecordBackend record backend, MonadIO m1, MonadIO m2)            => [Filter record]@@ -66,6 +72,11 @@  -- | Get all records matching the given criterion in the specified order. -- Returns also the identifiers.+--+-- WARNING: This function returns a 'ConduitM', which implies that it streams+-- the results. It does not stream results on most backends. If you need+-- streaming, see @persistent-pagination@ for a means of chunking results based+-- on indexed ranges. selectSource        :: forall record backend m. (PersistQueryRead backend, MonadResource m, PersistRecordBackend record backend, MonadReader backend m)        => [Filter record]@@ -78,6 +89,8 @@     release releaseKey  -- | Get the 'Key's of all records matching the given criterion.+--+-- For an example, see 'selectList'. selectKeys :: forall record backend m. (PersistQueryRead backend, MonadResource m, PersistRecordBackend record backend, MonadReader backend m)            => [Filter record]            -> [SelectOpt record]@@ -88,11 +101,64 @@     src     release releaseKey --- | Call 'selectSource' but return the result as a list.-selectList :: forall record backend m. (MonadIO m, PersistQueryRead backend, PersistRecordBackend record backend)-           => [Filter record]-           -> [SelectOpt record]-           -> ReaderT backend m [Entity record]+-- | Returns a @['Entity' record]@ corresponding to the filters and options+-- provided.+--+-- Filters are constructed using the operators defined in "Database.Persist"+-- (and re-exported from "Database.Persist.Sql"). Let's look at some examples:+--+-- @+-- usersWithAgeOver40 :: 'SqlPersistT' 'IO' ['Entity' User]+-- usersWithAgeOver40 =+--     'selectList' [UserAge 'Database.Persist.>=.' 40] []+-- @+--+-- If you provide multiple values in the list, the conditions are @AND@ed+-- together.+--+-- @+-- usersWithAgeBetween30And50 :: 'SqlPersistT' 'IO' ['Entity' User]+-- usersWithAgeBetween30And50 =+--      'selectList'+--          [ UserAge 'Database.Persist.>=.' 30+--          , UserAge 'Database.Persist.<=.' 50+--          ]+--          []+-- @+--+-- The second list contains the 'SelectOpt' for a record.  We can select the+-- first ten records with 'LimitTo'+--+-- @+-- firstTenUsers =+--     'selectList' [] ['LimitTo' 10]+-- @+--+-- And we can select the second ten users with 'OffsetBy'.+--+-- @+-- secondTenUsers =+--     'selectList' [] ['LimitTo' 10, 'OffsetBy' 10]+-- @+--+-- <https://use-the-index-luke.com/sql/partial-results/fetch-next-page Warning that LIMIT/OFFSET is bad for pagination!>+--+-- With 'Asc' and 'Desc', we can provide the field we want to sort on. We can+-- provide multiple sort orders - later ones are used to sort records that are+-- equal on the first field.+--+-- @+-- newestUsers =+--     selectList [] ['Desc' UserCreatedAt, 'LimitTo' 10]+--+-- oldestUsers =+--     selectList [] ['Asc' UserCreatedAt, 'LimitTo' 10]+-- @+selectList+    :: forall record backend m. (MonadIO m, PersistQueryRead backend, PersistRecordBackend record backend)+    => [Filter record]+    -> [SelectOpt record]+    -> ReaderT backend m [Entity record] selectList filts opts = do     srcRes <- selectSourceRes filts opts     liftIO $ with srcRes (\src -> runConduit $ src .| CL.consume)
Database/Persist/Quasi.hs view
@@ -66,7 +66,7 @@ = Setting defaults  You can use a @default=${sql expression}@ clause to set a default for a field.-The thing following the `=` is interpreted as SQL that will be put directly into the table definition.+The thing following the @=@ is interpreted as SQL that will be put directly into the table definition.  @ User@@ -82,7 +82,7 @@ >   admin   BOOL DEFAULT=false > ); -A restriction here is that you still need to provide a value when performing an `insert`, because the generated Haskell type has the form:+A restriction here is that you still need to provide a value when performing an @insert@, because the generated Haskell type has the form:  @ data User = User@@ -93,6 +93,28 @@  You can work around this by using a 'Maybe Bool' and supplying 'Nothing' by default. +__Note__: Persistent determines whether or not to migrate a column's default+value by comparing the exact string found in your @models@ file with the one+returned by the database. If a database canonicalizes the SQL @FALSE@ from your+@models@ file to @false@ in the database, Persistent will think the default+value needs to be migrated and+<https://github.com/yesodweb/persistent/issues/241 attempt a migration each time you start your app>.++To workaround this, find the exact SQL your DBMS uses for the default value. For example, using postgres:++@+psql database_name # Open postgres++\\d+ table_name -- describe the table schema+@++@+...+created       | timestamp without time zone | not null default now()+@++Then use the listed default value SQL inside your @models@ file.+ = Custom ID column  If you don't want to use the default ID column type of 'Int64', you can set a custom type with an @Id@ field.@@ -171,11 +193,145 @@ ); @ -= Attributes+= Customizing Types/Tables +== JSON instances++You can automatically get ToJSON and FromJSON instances for any entity by adding @json@ to the entity line:++@+Person json+    name Text+@+Requires @{-# LANGUAGE FlexibleInstances #-}@++Customizable by using mpsEntityJSON+* http://hackage.haskell.org/package/persistent-template/docs/Database-Persist-TH.html#v:EntityJSON+* http://hackage.haskell.org/package/persistent/docs/Database-Persist-Class.html#v:keyValueEntityToJSON++== Changing table/collection name++@+Person sql=peoples+    name Text+@++== Change table/collection key definition (field name and/or type, persistent >= 2.1)++@Id@ defines the column to use to define the key of the entity.+Without type, the default backend key type will be used. You can change its+database name using the @sql@ attributes :++@+Person+   Id         sql=my_id_name+   phone Text+@++With a Haskell type, the corresponding type is used. Note that you'll need to+use @default=@ to tell it what to do on insertion.++@+Person+   Id    Day default=CURRENT_DATE+   phone Text+@++@default=@ works for SQL databases, and is backend specific.+For MongoDB currently one always needs to create the key on the application+side and use @insertKey@. @insert@ will not work correctly. Sql backends can+also do this if default does not work.++@sqltype@ can also be used to specify a different database type++@+Currency+    Id String sqltype=varchar(3) sql=code+@++Composite key (using multiple columns) can also be defined using @Primary@.++@sql=@ also works for setting the names of unique indexes.++@+Person+  name Text+  phone Text+  UniquePersonPhone phone sql=UniqPerPhone+@++This makes a unique index requiring @phone@ to be unique across @Person@ rows.+Ordinarily Persistent will generate a snake-case index name from the+capitalized name provided such that @UniquePersonPhone@ becomes+@unique_person_phone@. However, we provided a @sql=@ so the index name in the+database will instead be @UniqPerPhone@. Keep in mind @sql=@ and @!@ attrs must+come after the list of fields in front of the index name in the quasi-quoter.++++= Customizing Fields++== Nullable Fields++As illustrated in the example at the beginning of this page, we are able to represent nullable+fields by including 'Maybe' at the end of the type declaration:++> TableName+>     fieldName      FieldType+>     otherField     String+>     nullableField  Int       Maybe++Alternatively we can specify the keyword nullable:++> TableName+>     fieldName      FieldType+>     otherField     String+>     nullableField  Int       nullable++However the difference here is in the first instance the Haskell type will be 'Maybe Int',+but in the second it will be 'Int'. Be aware that this will cause runtime errors if the+database returns @NULL@ and the @PersistField@ instance does not handle @PersistNull@.++If you wish to define your Maybe types in a way that is similar to the actual Haskell+definition, you can define 'Maybe Int' like so:++> TableName+>     fieldName      FieldType+>     otherField     String+>     nullableField  (Maybe Int)++However, note, the field _must_ be enclosed in parenthesis.++== @sqltype=@++By default, Persistent maps the Haskell types you specify in the Models DSL to+an appropriate SQL type in the database (refer to the section "Conversion table+(migrations)" for the default mappings). Using the+@sqltype=@ option, you can  customize the SQL type Persistent uses for your+column. Use cases include:++* Interacting with an existing database whose column types don't match Persistent's defaults.+* Taking advantage of a specific SQL type's features+    * e.g. Using an equivalent type that has better space or performance characteristics++To use this setting, add the @sqltype=@ option after declaring your field name and type:++@+User+    username Text sqltype=varchar(255)+@++== Laziness++By default the records created by persistent have strict fields. You can prefix+a field name with @~@ to make it lazy (or @!@ to make it strict).++== Attributes+ The QuasiQuoter allows you to provide arbitrary attributes to an entity or field. This can be used to extend the code in ways that the library hasn't anticipated.-If you use this feature, we'd definitely appreciate hearing about it and potentially supporting your use case directly!+If you use this feature, we'd definitely appreciate hearing about it and+potentially supporting your use case directly!  @ User !funny@@ -196,6 +352,40 @@ -- [["sad"],["sogood"]] @ +== @MigrationOnly@++Introduced with @persistent-template@ 1.2.0. The purpose of this attribute is+to mark a field which will be entirely ignored by the normal processing, but+retained in the database definition for purposes of migration. This means, in+SQL, a column will not be flagged for removal by the migration scripts, even+though it is not used in your code. This is useful for phasing out usage of a+column before entirely removing it, or having columns which are needed by other+tools but not by Persistent.++@+Person+    name Text+    age Int+    unusedField ByteString Maybe MigrationOnly+@++Note that you almost certainly want to either mark the field as @Maybe@ or+provide a default value, otherwise insertions will fail.+++== @SafeToRemove@++This is intended to be used as part of a deprecation of a field, after+@MigrationOnly@ has been used usually. This works somewhat as a superset of the+functionality of @MigrationOnly@. In addition, the field will be removed from+the database if it is present. Note that this is a destructive change which you+are marking as safe.++== Constraints++Migration will remove any manual constraints from your tables. Exception: constraints whose names begin with the string @__manual_@ (which starts with two underscores) will be preserved.++ = Foreign Keys  If you define an entity and want to refer to it in another table, you can use the entity's Id type in a column directly.@@ -213,6 +403,21 @@ The foreign key constraint means that, if you have a @PersonId@ on the @Dog@, the database guarantees that the corresponding @Person@ exists in the database. If you try to delete a @Person@ out of the database that has a @Dog@, you'll receive an exception that a foreign key violation has occurred. +== @constraint=@++You can use the @constraint=@ attribute to override the constraint name used in+migrations. This is useful particularly when the automatically generated+constraint names exceed database limits (e.g. MySQL does not allow constraint+names longer than 64 characters).++@+VeryLongTableName+  name Text++AnotherVeryLongTableName+  veryLongTableNameId VeryLongTableNameId constraint=short_foreign_key+@+ == OnUpdate and OnDelete  These options affects how a referring record behaves when the target record is changed.@@ -366,37 +571,6 @@     Foreign User fk_noti_user sentToFirst sentToSecond References emailFirst emailSecond @ -= Nullable Fields--As illustrated in the example at the beginning of this page, we are able to represent nullable-fields by including 'Maybe' at the end of the type declaration:--> TableName->     fieldName      FieldType->     otherField     String->     nullableField  Int       Maybe--Alternatively we can specify the keyword nullable:--> TableName->     fieldName      FieldType->     otherField     String->     nullableField  Int       nullable--However the difference here is in the first instance the Haskell type will be 'Maybe Int',-but in the second it will be 'Int'. Be aware that this will cause runtime errors if the-database returns `NULL` and the `PersistField` instance does not handle `PersistNull`.--If you wish to define your Maybe types in a way that is similar to the actual Haskell-definition, you can define 'Maybe Int' like so:--> TableName->     fieldName      FieldType->     otherField     String->     nullableField  (Maybe Int)--However, note, the field _must_ be enclosed in parenthesis.- = Documentation Comments  The quasiquoter supports ordinary comments with @--@ and @#@.@@ -420,7 +594,7 @@     age Int @ -The documentation is present on the `entityComments` field on the `EntityDef` for the entity:+The documentation is present on the @entityComments@ field on the @EntityDef@ for the entity:  @ >>> let userDefinition = entityDef (Proxy :: Proxy User)@@ -428,7 +602,7 @@ "I am a doc comment for a User. Users are important\nto the application, and should be treasured.\n" @ -Likewise, the field documentation is present in the `fieldComments` field on the `FieldDef` present in the `EntityDef`:+Likewise, the field documentation is present in the @fieldComments@ field on the @FieldDef@ present in the @EntityDef@:  @ >>> let userFields = entityFields userDefinition@@ -439,8 +613,292 @@ @  Unfortunately, we can't use this to create Haddocks for you, because <https://gitlab.haskell.org/ghc/ghc/issues/5467 Template Haskell does not support Haddock yet>.-`persistent` backends *can* use this to generate SQL @COMMENT@s, which are useful for a database perspective, and you can use the <https://hackage.haskell.org/package/persistent-documentation @persistent-documentation@> library to render a Markdown document of the entity definitions.+@persistent@ backends *can* use this to generate SQL @COMMENT@s, which are useful for a database perspective, and you can use the <https://hackage.haskell.org/package/persistent-documentation @persistent-documentation@> library to render a Markdown document of the entity definitions. += Sum types++== Field level++You'll frequently want to store an enum of values in your database. For+example, you might describe a @Person@'s employment status as being @Employed@,+@Unemployed@, or @Retired@. In Haskell this is represented with a sum type, and+Persistent provides a Template Haskell function to marshall these values to and+from the database:++@+-- @Employment.hs+{-# LANGUAGE TemplateHaskell #-}+module Employment where++import Database.Persist.TH+import Prelude++data Employment = Employed | Unemployed | Retired+    deriving (Show, Read, Eq)+derivePersistField "Employment"+@++@derivePersistField@ stores sum type values as strins in the database. While not as efficient as using integers, this approach simplifies adding and removing values from your enumeration.++Due to the GHC Stage Restriction, the call to the Template Haskell function @derivePersistField@ must be in a separate module than where the generated code is used.++Note: If you created a new module, make sure add it to the @exposed-modules@ section of your Cabal file.++Use the module by importing it into your @Model.hs@ file:++@+-- @Model.hs+import Employment+@++and use it in the @models@ DSL:++@+Person+    employment Employment+@++You can export the Employment module from Import to use it across your app:++@+-- @Import.hs+import Employment as Import+@++=== Entity-level++The+<https://github.com/yesodweb/persistent/blob/master/persistent-test/src/SumTypeTest.hs#L35 tests for this feature>+demonstrate their usage. Note the use of the sign @+@ in front of the entity+name.++The schema in the test is reproduced here:++@+share [mkPersist persistSettings, mkMigrate "sumTypeMigrate"] [persistLowerCase|+Bicycle+    brand T.Text+Car+    make T.Text+    model T.Text++Vehicle+    bicycle BicycleId+    car CarId+|]+@++Let's check out the definition of the Haskell type @Vehicle@.+Using @ghci@, we can query for @:info Vehicle@:++>>> :i Vehicle+type Vehicle = VehicleGeneric SqlBackend+        -- Defined at .../Projects/persistent/persistent-test/src/SumTypeTest.hs:26:1++>>> :i VehicleGeneric+type role VehicleGeneric nominal+data VehicleGeneric backend+  = VehicleBicycleSum (Key (BicycleGeneric backend))+  | VehicleCarSum (Key (CarGeneric backend))+        -- Defined at .../persistent/persistent-test/src/SumTypeTest.hs:26:1+-- lots of instances follow...++A @VehicleGeneric@ has two constructors:++- @VehicleBicycleSum@ with a @Key (BicycleGeneric backend)@ field+- @VehicleCarSum@ with a @Key (CarGeneric backend)@ field++The @Bicycle@ and @Car@ are typical @persistent@ entities.++This generates the following SQL migrations (formatted for readability):++@+CREATE TABLE "bicycle" (+    "id"        INTEGER PRIMARY KEY,+    "brand"     VARCHAR NOT NULL+);++CREATE TABLE "car"(+    "id"        INTEGER PRIMARY KEY,+    "make"      VARCHAR NOT NULL,+    "model"     VARCHAR NOT NULL+);++CREATE TABLE "vehicle"(+    "id"        INTEGER PRIMARY KEY,+    "bicycle"   INTEGER NULL REFERENCES "bicycle",+    "car"       INTEGER NULL REFERENCES "car"+);+@++The @vehicle@ table contains a nullable foreign key reference to both the bicycle and the car tables.++A SQL query that grabs all the vehicles from the database looks like this (note the @??@ is for the @persistent@ raw SQL query functions):++@+SELECT ??, ??, ??+FROM vehicle+LEFT JOIN car+    ON vehicle.car = car.id+LEFT JOIN bicycle+    ON vehicle.bicycle = bicycle.id+@++If we use the above query with @rawSql@, we'd get the following result:++@+getVehicles+    :: SqlPersistM+        [ ( Entity Vehicle+          , Maybe (Entity Bicycle)+          , Maybe (Entity Car)+          )+        ]+@++This result has some post-conditions that are not guaranteed by the types *or* the schema.+The constructor for @Entity Vehicle@ is going to determine which of the other members of the tuple is @Nothing@.+We can convert this to a friendlier domain model like this:++@+data Vehicle'+    = Car' Text Text+    | Bike Text++check = do+    result <- getVehicles+    pure (map convert result)++convert+    :: (Entity Vehicle, Maybe (Entity Bicycle), Maybe (Entity Car))+    -> Vehicle'+convert (Entity _ (VehicycleBicycleSum _), Just (Entity _ (Bicycle brand)), _) =+    Bike brand+convert (Entity _ (VehicycleCarSum _), _, Just (Entity _ (Car make model))) =+    Car make model+convert _ =+    error "The database preconditions have been violated!"+@++== Times with timezones++Storing times with timezones in one type in databases is not possible, although+it seems that it should be possible (@timezone@ and @timezonetz@ in+PostgreSQL). That's why starting with persistent 2.0, all times will be mapped+to @UTCTime@. If you need to store timezone information along with times in a+database, store the timezone in a second field. Here are some links about the+topic with further information:++* https://github.com/yesodweb/persistent/issues/290+* https://groups.google.com/forum/#!msg/yesodweb/MIfcV2bwM80/8QLFpgp1LykJ+* http://stackoverflow.com/questions/14615271/postgres-timestamp/14616640#14616640+* http://justatheory.com/computers/databases/postgresql/use-timestamptz.html+* https://github.com/lpsmith/postgresql-simple/issues/69+* https://github.com/nikita-volkov/hasql-postgres/issues/1++= Conversion table (migrations)++Here are the conversions between Haskell types and database types:+++------------+----------------------+-------------------+---------------+----------------++| Haskell    | PostgreSQL           | MySQL             | MongoDB       |  SQLite        |++============+======================+===================+===============+================++| Text       |  VARCHAR             |  TEXT             | String        |  VARCHAR       |++------------+----------------------+-------------------+---------------+----------------++| ByteString |  BYTEA               |  BLOB             | BinData       |  BLOB          |++------------+----------------------+-------------------+---------------+----------------++| Int        |  INT8                |  BIGINT(20)       | NumberLong    |  INTEGER       |++------------+----------------------+-------------------+---------------+----------------++| Double     |  DOUBLE PRECISION    |  DOUBLE           | Double        |  REAL          |++------------+----------------------+-------------------+---------------+----------------++| Rational   |  NUMERIC(22, 12)     |  DECIMAL(32,20)   | *Unsupported* |  NUMERIC(32,20)|++------------+----------------------+-------------------+---------------+----------------++| Bool       |  BOOLEAN             |  TINYINT(1)       | Boolean       |  BOOLEAN       |++------------+----------------------+-------------------+---------------+----------------++| Day        |  DATE                |  DATE             | NumberLong    |  DATE          |++------------+----------------------+-------------------+---------------+----------------++| TimeOfDay  |  TIME                |  TIME\*\*         | *Unsupported* |  TIME          |++------------+----------------------+-------------------+---------------+----------------++| UTCTime\*  |  TIMESTAMP           |  DATETIME\*\*     | Date          |  TIMESTAMP     |++------------+----------------------+-------------------+---------------+----------------+++Notes:++\* Support for @ZonedTime@ was dropped in persistent 2.0. @UTCTime@ can be used+with @timestamp without timezone@ and @timestamp with timezone@ in PostgreSQL.+See also the section "Times with timezones".++\*\* The default resolution for @TIME@ and @DATETIME@ in MySQL is one second.+As of MySQL version 5.6.4, and persistent-mysql-2.6.2, fractional seconds are+handled correctly if you declare an explicit precision by using @sqltype@. For+example, appending @sqltype=TIME(6)@ to a @TimeOfDay@ field definition will+give microsecond resolution.++= Compatibility tables++MySQL:+++-------------------+-----------------------------------------------------------------------++|Haskell type       | Compatible MySQL types                                                |++===================+=======================================================================++| Bool              | Tiny                                                                  |++-------------------+-----------------------------------------------------------------------++| Int8              | Tiny                                                                  |++-------------------+-----------------------------------------------------------------------++| Int16             | Tiny,Short                                                            |++-------------------+-----------------------------------------------------------------------++| Int32             | Tiny,Short,Int24,Long                                                 |++-------------------+-----------------------------------------------------------------------++| Int               | Tiny,Short,Int24,Long,LongLong\*                                      |++-------------------+-----------------------------------------------------------------------++| Int64             | Tiny,Short,Int24,Long,LongLong                                        |++-------------------+-----------------------------------------------------------------------++| Integer           | Tiny,Short,Int24,Long,LongLong                                        |++-------------------+-----------------------------------------------------------------------++| Word8             | Tiny                                                                  |++-------------------+-----------------------------------------------------------------------++| Word16            | Tiny,Short                                                            |++-------------------+-----------------------------------------------------------------------++| Word32            | Tiny,Short,Int24,Long                                                 |++-------------------+-----------------------------------------------------------------------++| Word64            | Tiny,Short,Int24,Long,LongLong                                        |+| Double            | Float,Double,Decimal,NewDecimal,Tiny,Short,Int24,Long                 |++-------------------+-----------------------------------------------------------------------++| Ratio Integer     | Float,Double,Decimal,NewDecimal,Tiny,Short,Int24,Long,LongLong        |++-------------------+-----------------------------------------------------------------------++| ByteString        | VarChar,TinyBlob,MediumBlob,LongBlob,Blob,VarString,String,Set,Enum   |++-------------------+-----------------------------------------------------------------------++| Lazy.ByteString   | VarChar,TinyBlob,MediumBlob,LongBlob,Blob,VarString,String,Set,Enum   |++-------------------+-----------------------------------------------------------------------++| Encoding.Text\*\* | VarChar,TinyBlob,MediumBlob,LongBlob,Blob,VarString,String,Set,Enum   |++-------------------+-----------------------------------------------------------------------++| Lazy.Text         | VarChar,TinyBlob,MediumBlob,LongBlob,Blob,VarString,String,Set,Enum   |++-------------------+-----------------------------------------------------------------------++| [Char]/String     | VarChar,TinyBlob,MediumBlob,LongBlob,Blob,VarString,String,Set,Enum   |++-------------------+-----------------------------------------------------------------------++| UTCTime           | DateTime,Timestamp                                                    |++-------------------+-----------------------------------------------------------------------++| Day               | Year,Date,NewDate                                                     |++-------------------+-----------------------------------------------------------------------++| TimeOfDay         | Time                                                                  |++-------------------+-----------------------------------------------------------------------+++\* When @Word@ size is 64bit++\*\* Utf8 only++Unsupported types:+++--------------------------------------------------------------------++| Not currently supported                                            |++====================================================================++| Word                                                               |++--------------------------------------------------------------------++| Float                                                              |++--------------------------------------------------------------------++| Scientific <https://github.com/yesodweb/persistent/issues/225 #225>|++--------------------------------------------------------------------+++See <http://hackage.haskell.org/package/mysql-simple/docs/Database-MySQL-Simple-Result.html MySQL.Simple.Result>. -} module Database.Persist.Quasi     ( parse
Database/Persist/Sql.hs view
@@ -1,24 +1,50 @@+-- | This module is the primary entry point if you're working with @persistent@+-- on a SQL database.+--+-- = Getting Started+--+-- First, you'll want to define your database entities. You can do that with+-- "Database.Persist.Quasi."+--+-- Then, you'll use the operations module Database.Persist.Sql-    ( module Database.Persist.Sql.Types-    , module Database.Persist.Sql.Class+    (+    -- * 'RawSql' and 'PersistFieldSql'+      module Database.Persist.Sql.Class+    -- * Running actions+    -- | Run actions in a transaction with 'runSqlPool'.     , module Database.Persist.Sql.Run+    -- * Migrations     , module Database.Persist.Sql.Migration+    -- * @persistent@ combinators+    -- | We re-export "Database.Persist" here, to make it easier to use query+    -- and update combinators. Check out that module for documentation.     , module Database.Persist     , module Database.Persist.Sql.Orphan.PersistStore+    -- * The Escape Hatch+    -- | @persistent@ offers a set of functions that are useful for operating+    -- directly on the underlying SQL database. This can allow you to use+    -- whatever SQL features you want.+    --+    -- Consider going to <https://hackage.haskell.org/package/esqueleto+    -- esqueleto> for a more powerful SQL query library built on @persistent@.     , rawQuery     , rawQueryRes     , rawExecute     , rawExecuteCount     , rawSql+    -- * SQL helpers     , deleteWhereCount     , updateWhereCount     , filterClause     , filterClauseWithVals     , FilterTablePrefix (..)+    -- * Transactions     , transactionSave     , transactionSaveWithIsolation     , transactionUndo     , transactionUndoWithIsolation+    -- * Other utilities     , getStmtConn     , mkColumns     , BackendSpecificOverrides@@ -29,6 +55,7 @@       -- * Internal     , IsolationLevel(..)     , decorateSQLWithLimitOffset+    , module Database.Persist.Sql.Types     ) where  import Control.Monad.IO.Class
Database/Persist/Sql/Migration.hs view
@@ -1,8 +1,17 @@+-- | This module documents tools and utilities for running SQL migrations.+--+-- A 'Migration' is (currently) an alias for a 'WriterT' of module Database.Persist.Sql.Migration-  ( parseMigration+  (+    -- * Types+    Migration+  , CautiousMigration+  , Sql+    -- * Using a 'Migration'+  , showMigration+  , parseMigration   , parseMigration'   , printMigration-  , showMigration   , getMigration   , runMigration   , runMigrationQuiet@@ -11,11 +20,38 @@   , runMigrationUnsafeQuiet   , migrate   -- * Utilities for constructing migrations+  -- | While 'migrate' is capable of creating a 'Migration' for you, it's not+  -- the only way you can write migrations. You can use these utilities to write+  -- extra steps in your migrations.+  --+  -- As an example, let's say we want to enable the @citext@ extension on+  -- @postgres@ as part of our migrations.+  --+  -- @+  -- 'Database.Persist.TH.share' ['Database.Persist.TH.mkPersist' sqlSettings, 'Database.Persist.TH.mkMigration' "migrateAll"] ...+  --+  -- migration :: 'Migration'+  -- migration = do+  --     'runSqlCommand' $+  --         'rawExecute_' "CREATE EXTENSION IF NOT EXISTS \"citext\";"+  --     migrateAll+  -- @+  --+  -- For raw commands, you can also just write 'addMigration':+  --+  -- @+  -- migration :: 'Migration'+  -- migration = do+  --     'addMigration' "CREATE EXTENSION IF NOT EXISTS \"citext\";"+  --     migrateAll+  -- @   , reportErrors   , reportError   , addMigrations   , addMigration   , runSqlCommand+  -- * If something goes wrong...+  , PersistUnsafeMigrationException(..)   ) where  @@ -36,9 +72,29 @@ import Database.Persist.Sql.Types import Database.Persist.Sql.Types.Internal import Database.Persist.Types+import Control.Exception (Exception(..)) +type Sql = Text++-- | A list of SQL operations, marked with a safety flag. If the 'Bool' is+-- 'True', then the operation is *unsafe* - it might be destructive, or+-- otherwise not idempotent. If the 'Bool' is 'False', then the operation+-- is *safe*, and can be run repeatedly without issues.+type CautiousMigration = [(Bool, Sql)]++-- | A 'Migration' is a four level monad stack consisting of:+--+-- * @'WriterT' ['Text']@ representing a log of errors in the migrations.+-- * @'WriterT' 'CautiousMigration'@ representing a list of migrations to+--   run, along with whether or not they are safe.+-- * @'ReaderT' 'SqlBackend'@, aka the 'SqlPersistT' transformer for+--   database interop.+-- * @'IO'@ for arbitrary IO.+type Migration = WriterT [Text] (WriterT CautiousMigration (ReaderT SqlBackend IO)) ()+ allSql :: CautiousMigration -> [Sql] allSql = map snd+ safeSql :: CautiousMigration -> [Sql] safeSql = allSql . filter (not . fst) @@ -55,7 +111,7 @@  -- | Like 'parseMigration', but instead of returning the value in an -- 'Either' value, it calls 'error' on the error values.-parseMigration' :: (HasCallStack, MonadIO m) => Migration -> ReaderT SqlBackend m (CautiousMigration)+parseMigration' :: (HasCallStack, MonadIO m) => Migration -> ReaderT SqlBackend m CautiousMigration parseMigration' m = do   x <- parseMigration m   case x of@@ -82,7 +138,6 @@ -- | Runs a migration. If the migration fails to parse or if any of the -- migrations are unsafe, then this throws a 'PersistUnsafeMigrationException'. runMigration :: MonadIO m-              => Migration              -> ReaderT SqlBackend m () runMigration m = runMigration' m False >> return ()@@ -223,3 +278,29 @@ -- @since 2.13.0.0 runSqlCommand :: SqlPersistT IO () -> Migration runSqlCommand = lift . lift++-- | An exception indicating that Persistent refused to run some unsafe+-- migrations. Contains a list of pairs where the Bool tracks whether the+-- migration was unsafe (True means unsafe), and the Sql is the sql statement+-- for the migration.+--+-- @since 2.11.1.0+newtype PersistUnsafeMigrationException+  = PersistUnsafeMigrationException [(Bool, Sql)]++-- | This 'Show' instance renders an error message suitable for printing to the+-- console. This is a little dodgy, but since GHC uses Show instances when+-- displaying uncaught exceptions, we have little choice.+instance Show PersistUnsafeMigrationException where+  show (PersistUnsafeMigrationException mig) =+    concat+      [ "\n\nDatabase migration: manual intervention required.\n"+      , "The unsafe actions are prefixed by '***' below:\n\n"+      , unlines $ map displayMigration mig+      ]+    where+      displayMigration :: (Bool, Sql) -> String+      displayMigration (True,  s) = "*** " ++ unpack s ++ ";"+      displayMigration (False, s) = "    " ++ unpack s ++ ";"++instance Exception PersistUnsafeMigrationException
Database/Persist/Sql/Types.hs view
@@ -61,24 +61,6 @@  type SqlPersistM = SqlPersistT (NoLoggingT (ResourceT IO)) -type Sql = Text---- | A list of SQL operations, marked with a safety flag. If the 'Bool' is--- 'True', then the operation is *unsafe* - it might be destructive, or--- otherwise not idempotent. If the 'Bool' is 'False', then the operation--- is *safe*, and can be run repeatedly without issues.-type CautiousMigration = [(Bool, Sql)]---- | A 'Migration' is a four level monad stack consisting of:------ * @'WriterT' ['Text']@ representing a log of errors in the migrations.--- * @'WriterT' 'CautiousMigration'@ representing a list of migrations to---   run, along with whether or not they are safe.--- * @'ReaderT' 'SqlBackend'@, aka the 'SqlPersistT' transformer for---   database interop.--- * @'IO'@ for arbitrary IO.-type Migration = WriterT [Text] (WriterT CautiousMigration (ReaderT SqlBackend IO)) ()- type ConnectionPool = Pool SqlBackend  -- | Values to configure a pool of database connections. See "Data.Pool" for details.@@ -157,28 +139,3 @@ newtype Single a = Single {unSingle :: a}     deriving (Eq, Ord, Show, Read) --- | An exception indicating that Persistent refused to run some unsafe--- migrations. Contains a list of pairs where the Bool tracks whether the--- migration was unsafe (True means unsafe), and the Sql is the sql statement--- for the migration.------ @since 2.11.1.0-newtype PersistUnsafeMigrationException-  = PersistUnsafeMigrationException [(Bool, Sql)]---- | This 'Show' instance renders an error message suitable for printing to the--- console. This is a little dodgy, but since GHC uses Show instances when--- displaying uncaught exceptions, we have little choice.-instance Show PersistUnsafeMigrationException where-  show (PersistUnsafeMigrationException mig) =-    concat-      [ "\n\nDatabase migration: manual intervention required.\n"-      , "The unsafe actions are prefixed by '***' below:\n\n"-      , unlines $ map displayMigration mig-      ]-    where-      displayMigration :: (Bool, Sql) -> String-      displayMigration (True,  s) = "*** " ++ unpack s ++ ";"-      displayMigration (False, s) = "    " ++ unpack s ++ ";"--instance Exception PersistUnsafeMigrationException
Database/Persist/Sql/Util.hs view
@@ -49,10 +49,9 @@        , toPersistValue        ) -import Database.Persist.Sql.Types (Sql) import Database.Persist.SqlBackend.Internal (SqlBackend(..)) -keyAndEntityColumnNames :: EntityDef -> SqlBackend -> NonEmpty Sql+keyAndEntityColumnNames :: EntityDef -> SqlBackend -> NonEmpty Text keyAndEntityColumnNames ent conn =     fmap (connEscapeFieldName conn . fieldDB) (keyAndEntityFields ent) 
Database/Persist/Types.hs view
@@ -1,9 +1,29 @@+-- | This module exports many types and functions for operating on+-- @persistent@'s database representation. It's a bit of a kitchen sink. In the+-- future, this module will be reorganized, and many of the dependent modules+-- will be viewable on their own for easier documentation and organization. module Database.Persist.Types-    ( module Database.Persist.Types.Base-    , module Database.Persist.Names+    (+    -- * Various Types of Names+    -- | There are so many kinds of names. @persistent@ defines newtype wrappers+    -- for 'Text' so you don't confuse what a name is and what it is+    -- supposed to be used for+      module Database.Persist.Names+    -- * Database Definitions+    -- ** Entity/Table Definitions+    -- | The 'EntityDef' type is used by @persistent@ to generate Haskell code,+    -- generate database migrations, and maintain metadata about entities. These+    -- are generated in the call to 'Database.Persist.TH.mkPersist'.     , module Database.Persist.EntityDef+    -- ** Field definitions+    -- | The 'FieldDef' type is used to describe how a field should be+    -- represented at the Haskell and database layers.     , module Database.Persist.FieldDef+    -- * Intermediate Values+    -- | The 'PersistValue' type is used as an intermediate layer between+    -- database and Haskell types.     , module Database.Persist.PersistValue+    -- * Other Useful Stuff     , SomePersistField (..)     , Update (..)     , BackendSpecificUpdate@@ -14,6 +34,8 @@     , Key     , Entity (..)     , OverflowNatural(..)+    -- * The rest of the types+    , module Database.Persist.Types.Base     ) where  import Database.Persist.Class.PersistEntity
persistent.cabal view
@@ -1,5 +1,5 @@ name:            persistent-version:         2.13.1.1+version:         2.13.1.2 license:         MIT license-file:    LICENSE author:          Michael Snoyman <michael@snoyman.com>@@ -67,8 +67,9 @@         Database.Persist.Quasi.Internal          Database.Persist.Sql-        Database.Persist.Sql.Util+        Database.Persist.Sql.Migration         Database.Persist.Sql.Types.Internal+        Database.Persist.Sql.Util          Database.Persist.SqlBackend         Database.Persist.SqlBackend.Internal@@ -89,7 +90,6 @@     other-modules:            Database.Persist.Types.Base -        Database.Persist.Sql.Migration         Database.Persist.Sql.Internal         Database.Persist.Sql.Types         Database.Persist.Sql.Raw