Support upcoming persistent-2.13 (#245)

* stack-8.8.yaml now does GHC 8.8

* support ghc 8.10.4, upgrade to cabal 3.4

* do it

* use stack 8.10 by default, support pers2.13

* sqlite tests are failing???

* build with cabal

* gitignore

* tidy up

* work with persistent-2.13

* giddyup

* keep cabal file in repo

* fixx

* changelog, vbump

* update cache keys
This commit is contained in:
Matt Parsons 2021-05-05 16:23:53 -06:00 committed by GitHub
parent 9fba3e33e4
commit cd16b2b22f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 308 additions and 190 deletions

View File

@ -32,8 +32,8 @@ jobs:
--health-retries=3 --health-retries=3
strategy: strategy:
matrix: matrix:
cabal: ["3.2"] cabal: ["3.4"]
ghc: ["8.6.5", "8.8.3", "8.10.1"] ghc: ["8.6.5", "8.8.4", "8.10.4"]
env: env:
CONFIG: "--enable-tests --enable-benchmarks " CONFIG: "--enable-tests --enable-benchmarks "
steps: steps:
@ -68,6 +68,7 @@ jobs:
dist-newstyle dist-newstyle
key: ${{ runner.os }}-${{ matrix.ghc }}-${{ hashFiles('cabal.project.freeze') }} key: ${{ runner.os }}-${{ matrix.ghc }}-${{ hashFiles('cabal.project.freeze') }}
restore-keys: | restore-keys: |
${{ runner.os }}-${{ matrix.ghc }}-${{ hashFiles('cabal.project.freeze') }}
${{ runner.os }}-${{ matrix.ghc }}- ${{ runner.os }}-${{ matrix.ghc }}-
- run: cabal v2-build --disable-optimization -j $CONFIG - run: cabal v2-build --disable-optimization -j $CONFIG
- run: cabal v2-test --disable-optimization -j $CONFIG - run: cabal v2-test --disable-optimization -j $CONFIG

2
.gitignore vendored
View File

@ -1,7 +1,9 @@
.stack-work .stack-work
stack.yaml.lock stack.yaml.lock
*.yaml.lock
/dist* /dist*
*~ *~
.cabal-sandbox/ .cabal-sandbox/
cabal.sandbox.config cabal.sandbox.config
.hspec-failures .hspec-failures
cabal.project.freeze

View File

@ -1 +1,5 @@
packages: . -- Generated by stackage-to-hackage
packages:
./
, examples/

View File

@ -1,3 +1,9 @@
3.4.2.1
=======
- @parsonsmatt
- [#245](https://github.com/bitemyapp/esqueleto/pull/245)
- Support `persistent-2.13`
3.4.2.0 3.4.2.0
======= =======
- @parsonsmatt - @parsonsmatt

View File

@ -1,7 +1,7 @@
cabal-version: 1.12 cabal-version: 1.12
name: esqueleto name: esqueleto
version: 3.4.2.0 version: 3.4.2.1
synopsis: Type-safe EDSL for SQL queries on persistent backends. synopsis: Type-safe EDSL for SQL queries on persistent backends.
description: @esqueleto@ is a bare bones, type-safe EDSL for SQL queries that works with unmodified @persistent@ SQL backends. Its language closely resembles SQL, so you don't have to learn new concepts, just new syntax, and it's fairly easy to predict the generated SQL and optimize it for your backend. Most kinds of errors committed when writing SQL are caught as compile-time errors---although it is possible to write type-checked @esqueleto@ queries that fail at runtime. description: @esqueleto@ is a bare bones, type-safe EDSL for SQL queries that works with unmodified @persistent@ SQL backends. Its language closely resembles SQL, so you don't have to learn new concepts, just new syntax, and it's fairly easy to predict the generated SQL and optimize it for your backend. Most kinds of errors committed when writing SQL are caught as compile-time errors---although it is possible to write type-checked @esqueleto@ queries that fail at runtime.
. .
@ -53,7 +53,7 @@ library
, conduit >=1.3 , conduit >=1.3
, containers , containers
, monad-logger , monad-logger
, persistent >=2.12 && <2.13 , persistent >=2.13 && <3
, resourcet >=1.2 , resourcet >=1.2
, tagged >=0.2 , tagged >=0.2
, text >=0.11 && <1.3 , text >=0.11 && <1.3
@ -154,7 +154,7 @@ test-suite sqlite
Paths_esqueleto Paths_esqueleto
hs-source-dirs: hs-source-dirs:
test test
ghc-options: -Wall ghc-options: -Wall -threaded
build-depends: build-depends:
base >=4.8 && <5.0 base >=4.8 && <5.0
, attoparsec , attoparsec

1
examples/.gitignore vendored
View File

@ -1 +0,0 @@
*.cabal

View File

@ -0,0 +1,49 @@
cabal-version: 1.12
-- This file has been generated from package.yaml by hpack version 0.34.4.
--
-- see: https://github.com/sol/hpack
--
-- hash: d5fddaf37d0c2f27fb2446f5038899d766102efd74ccfe4c7bcd02c61837e6b6
name: esqueleto-examples
version: 0.0.0.0
category: Database
homepage: https://github.com/bitemyapp/esqueleto#readme
bug-reports: https://github.com/bitemyapp/esqueleto/issues
author: Fintan Halpenny
maintainer: cma@bitemyapp.com
copyright: 2019, Chris Allen
license: BSD3
license-file: LICENSE
build-type: Simple
extra-source-files:
README.md
source-repository head
type: git
location: https://github.com/bitemyapp/esqueleto
flag werror
description: Treat warnings as errors
manual: True
default: False
executable blog-example
main-is: Main.hs
other-modules:
Blog
ghc-options: -Wall -threaded -rtsopts -with-rtsopts=-N
build-depends:
base
, esqueleto
, monad-control
, monad-logger
, mtl
, persistent >=2.12
, persistent-postgresql
, transformers-base
, unliftio-core
if flag(werror)
ghc-options: -Werror
default-language: Haskell2010

View File

@ -13,8 +13,7 @@ extra-source-files:
dependencies: dependencies:
- base - base
- esqueleto - esqueleto
- persistent - persistent >= 2.12
- persistent-template
- persistent-postgresql - persistent-postgresql
- mtl - mtl
- monad-logger - monad-logger

View File

@ -1041,7 +1041,7 @@ from parts = do
runFrom :: From a -> SqlQuery (a, FromClause) runFrom :: From a -> SqlQuery (a, FromClause)
runFrom e@Table = do runFrom e@Table = do
let ed = entityDef $ getVal e let ed = entityDef $ getVal e
ident <- newIdentFor . DBName . unEntityNameDB $ entityDB ed ident <- newIdentFor . DBName . unEntityNameDB $ getEntityDBName ed
let entity = EEntity ident let entity = EEntity ident
pure $ (entity, FromStart ident ed) pure $ (entity, FromStart ident ed)
where where

View File

@ -16,6 +16,7 @@ import qualified Data.Set as Set
import Data.Text (Text) import Data.Text (Text)
import qualified Data.Text as Text import qualified Data.Text as Text
import Database.Persist.Sql import Database.Persist.Sql
import Database.Persist.SqlBackend
-- | A type representing the access of a table value. In Esqueleto, we get -- | A type representing the access of a table value. In Esqueleto, we get
-- a guarantee that the access will look something like: -- a guarantee that the access will look something like:
@ -43,7 +44,7 @@ parseOnExpr sqlBackend text = do
-- with postgresql, mysql, and sqlite backends. -- with postgresql, mysql, and sqlite backends.
mkEscapeChar :: SqlBackend -> Either String Char mkEscapeChar :: SqlBackend -> Either String Char
mkEscapeChar sqlBackend = mkEscapeChar sqlBackend =
case Text.uncons (connEscapeRawName sqlBackend "") of case Text.uncons (getEscapedRawName "" sqlBackend) of
Nothing -> Nothing ->
Left "Failed to get an escape character from the SQL backend." Left "Failed to get an escape character from the SQL backend."
Just (c, _) -> Just (c, _) ->
@ -63,9 +64,9 @@ skipToEscape escapeChar = void (takeWhile (/= escapeChar))
parseEscapedIdentifier :: ExprParser [Char] parseEscapedIdentifier :: ExprParser [Char]
parseEscapedIdentifier escapeChar = do parseEscapedIdentifier escapeChar = do
char escapeChar _ <- char escapeChar
str <- parseEscapedChars escapeChar str <- parseEscapedChars escapeChar
char escapeChar _ <- char escapeChar
pure str pure str
parseTableAccess :: ExprParser TableAccess parseTableAccess :: ExprParser TableAccess

View File

@ -15,6 +15,8 @@
{-# LANGUAGE TypeFamilies #-} {-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE UndecidableInstances #-} {-# LANGUAGE UndecidableInstances #-}
{-# OPTIONS_GHC -fno-warn-redundant-constraints #-}
-- | This is an internal module, anything exported by this module -- | This is an internal module, anything exported by this module
-- may change without a major version bump. Please use only -- may change without a major version bump. Please use only
-- "Database.Esqueleto" if possible. -- "Database.Esqueleto" if possible.
@ -23,6 +25,8 @@
-- tracker so we can safely support it. -- tracker so we can safely support it.
module Database.Esqueleto.Internal.Internal where module Database.Esqueleto.Internal.Internal where
import Data.List.NonEmpty (NonEmpty(..))
import qualified Data.List.NonEmpty as NEL
import Control.Applicative ((<|>)) import Control.Applicative ((<|>))
import Control.Arrow (first, (***)) import Control.Arrow (first, (***))
import Control.Exception (Exception, throw, throwIO) import Control.Exception (Exception, throw, throwIO)
@ -55,12 +59,13 @@ import qualified Data.Text.Lazy.Builder as TLB
import Data.Typeable (Typeable) import Data.Typeable (Typeable)
import Database.Esqueleto.Internal.ExprParser (TableAccess(..), parseOnExpr) import Database.Esqueleto.Internal.ExprParser (TableAccess(..), parseOnExpr)
import Database.Esqueleto.Internal.PersistentImport import Database.Esqueleto.Internal.PersistentImport
import Database.Persist.SqlBackend
import qualified Database.Persist import qualified Database.Persist
import Database.Persist (FieldNameDB(..), EntityNameDB(..)) import Database.Persist (FieldNameDB(..), EntityNameDB(..))
import Database.Persist.Sql.Util import Database.Persist.Sql.Util
( entityColumnCount ( entityColumnCount
, entityColumnNames , keyAndEntityColumnNames
, hasCompositeKey , hasNaturalKey
, isIdField , isIdField
, parseEntityValues , parseEntityValues
) )
@ -88,7 +93,7 @@ fromStart
=> SqlQuery (SqlExpr (PreprocessedFrom (SqlExpr (Entity a)))) => SqlQuery (SqlExpr (PreprocessedFrom (SqlExpr (Entity a))))
fromStart = do fromStart = do
let ed = entityDef (Proxy :: Proxy a) let ed = entityDef (Proxy :: Proxy a)
ident <- newIdentFor (coerce $ entityDB ed) ident <- newIdentFor (coerce $ getEntityDBName ed)
let ret = EEntity ident let ret = EEntity ident
f' = FromStart ident ed f' = FromStart ident ed
return (EPreprocessedFrom ret f') return (EPreprocessedFrom ret f')
@ -537,7 +542,7 @@ subSelectUnsafe = sub SELECT
fieldDef = fieldDef =
if isIdField field then if isIdField field then
-- TODO what about composite natural keys in a join this will ignore them -- TODO what about composite natural keys in a join this will ignore them
head $ entityKeyFields ed NEL.head $ getEntityKeyFields ed
else else
persistFieldDef field persistFieldDef field
@ -548,12 +553,12 @@ e ^. field
| otherwise = ERaw Never $ \info -> (dot info $ persistFieldDef field, []) | otherwise = ERaw Never $ \info -> (dot info $ persistFieldDef field, [])
where where
idFieldValue = idFieldValue =
case entityKeyFields ed of case getEntityKeyFields ed of
idField:[] -> idField :| [] ->
ERaw Never $ \info -> (dot info idField, []) ERaw Never $ \info -> (dot info idField, [])
idFields -> idFields ->
ECompositeKey $ \info -> dot info <$> idFields ECompositeKey $ \info -> NEL.toList $ dot info <$> idFields
ed = entityDef $ getEntityVal (Proxy :: Proxy (SqlExpr (Entity val))) ed = entityDef $ getEntityVal (Proxy :: Proxy (SqlExpr (Entity val)))
@ -1287,7 +1292,7 @@ toUniqueDef uniqueConstructor = uniqueDef
unique = finalR uniqueConstructor unique = finalR uniqueConstructor
-- there must be a better way to get the constrain name from a unique, make this not a list search -- there must be a better way to get the constrain name from a unique, make this not a list search
filterF = (==) (persistUniqueToFieldNames unique) . uniqueFields filterF = (==) (persistUniqueToFieldNames unique) . uniqueFields
uniqueDef = head . filter filterF . entityUniques . entityDef $ proxy uniqueDef = head . filter filterF . getEntityUniques . entityDef $ proxy
-- | Render updates to be use in a SET clause for a given sql backend. -- | Render updates to be use in a SET clause for a given sql backend.
-- --
@ -1809,7 +1814,7 @@ instance Show FromClause where
"(FromIdent " <> show ident <> ")" "(FromIdent " <> show ident <> ")"
where where
dummy = SqlBackend dummy = mkSqlBackend MkSqlBackendArgs
{ connEscapeRawName = id { connEscapeRawName = id
} }
render' = T.unpack . renderExpr dummy render' = T.unpack . renderExpr dummy
@ -2018,6 +2023,43 @@ type IdentInfo = (SqlBackend, IdentState)
useIdent :: IdentInfo -> Ident -> TLB.Builder useIdent :: IdentInfo -> Ident -> TLB.Builder
useIdent info (I ident) = fromDBName info $ DBName ident useIdent info (I ident) = fromDBName info $ DBName ident
entityAsValue
:: SqlExpr (Entity val)
-> SqlExpr (Value (Entity val))
entityAsValue eent =
case eent of
EEntity ident ->
identToRaw ident
EAliasedEntity ident _ ->
identToRaw ident
EAliasedEntityReference _ ident ->
identToRaw ident
where
identToRaw ident =
ERaw Never $ \identInfo ->
( useIdent identInfo ident
, []
)
entityAsValueMaybe
:: SqlExpr (Maybe (Entity val))
-> SqlExpr (Value (Maybe (Entity val)))
entityAsValueMaybe (EMaybe eent) =
case eent of
EEntity ident ->
identToRaw ident
EAliasedEntity ident _ ->
identToRaw ident
EAliasedEntityReference _ ident ->
identToRaw ident
where
identToRaw ident =
ERaw Never $ \identInfo ->
( useIdent identInfo ident
, []
)
-- | An expression on the SQL backend. -- | An expression on the SQL backend.
-- --
-- There are many comments describing the constructors of this -- There are many comments describing the constructors of this
@ -2145,7 +2187,7 @@ sub :: PersistField a => Mode -> SqlQuery (SqlExpr (Value a)) -> SqlExpr (Value
sub mode query = ERaw Parens $ \info -> toRawSql mode info query sub mode query = ERaw Parens $ \info -> toRawSql mode info query
fromDBName :: IdentInfo -> DBName -> TLB.Builder fromDBName :: IdentInfo -> DBName -> TLB.Builder
fromDBName (conn, _) = TLB.fromText . connEscapeRawName conn . unDBName fromDBName (conn, _) = TLB.fromText . flip getEscapedRawName conn . unDBName
existsHelper :: SqlQuery () -> SqlExpr (Value Bool) existsHelper :: SqlQuery () -> SqlExpr (Value Bool)
existsHelper = sub SELECT . (>> return true) existsHelper = sub SELECT . (>> return true)
@ -2905,7 +2947,7 @@ makeFrom info mode fs = ret
(useIdent info ident, mempty) (useIdent info ident, mempty)
base ident@(I identText) def = base ident@(I identText) def =
let db@(DBName dbText) = coerce $ entityDB def let db@(DBName dbText) = coerce $ getEntityDBName def
in ( fromDBName info db <> in ( fromDBName info db <>
if dbText == identText if dbText == identText
then mempty then mempty
@ -3010,8 +3052,7 @@ makeOrderBy info is =
makeLimit :: IdentInfo -> LimitClause -> [OrderByClause] -> (TLB.Builder, [PersistValue]) makeLimit :: IdentInfo -> LimitClause -> [OrderByClause] -> (TLB.Builder, [PersistValue])
makeLimit (conn, _) (Limit ml mo) orderByClauses = makeLimit (conn, _) (Limit ml mo) orderByClauses =
let limitRaw = connLimitOffset conn (v ml, v mo) hasOrderClause "\n" let limitRaw = getConnLimitOffset (v ml, v mo) "\n" conn
hasOrderClause = not (null orderByClauses)
v = maybe 0 fromIntegral v = maybe 0 fromIntegral
in (TLB.fromText limitRaw, mempty) in (TLB.fromText limitRaw, mempty)
@ -3070,10 +3111,10 @@ instance SqlSelect (SqlExpr InsertFinal) InsertFinal where
let fields = let fields =
uncommas $ uncommas $
map (fromDBName info . coerce . fieldDB) $ map (fromDBName info . coerce . fieldDB) $
entityFields $ getEntityFields $
entityDef p entityDef p
table = table =
fromDBName info . DBName . coerce . entityDB . entityDef $ p fromDBName info . DBName . coerce . getEntityDBName . entityDef $ p
in in
("INSERT INTO " <> table <> parens fields <> "\n", []) ("INSERT INTO " <> table <> parens fields <> "\n", [])
sqlSelectCols info (EInsertFinal (EInsert _ f)) = f info sqlSelectCols info (EInsertFinal (EInsert _ f)) = f info
@ -3089,16 +3130,26 @@ instance SqlSelect () () where
unescapedColumnNames :: EntityDef -> [DBName] unescapedColumnNames :: EntityDef -> [DBName]
unescapedColumnNames ent = unescapedColumnNames ent =
(if hasCompositeKey ent then id else ( coerce (fieldDB (entityId ent)) :)) addIdColumn rest
$ map (coerce . fieldDB) (entityFields ent) where
rest =
map (coerce . fieldDB) (getEntityFields ent)
addIdColumn =
case getEntityId ent of
EntityIdField fd ->
(:) (coerce (fieldDB fd))
EntityIdNaturalKey _ ->
id
-- | You may return an 'Entity' from a 'select' query. -- | You may return an 'Entity' from a 'select' query.
instance PersistEntity a => SqlSelect (SqlExpr (Entity a)) (Entity a) where instance PersistEntity a => SqlSelect (SqlExpr (Entity a)) (Entity a) where
sqlSelectCols info expr@(EEntity ident) = ret sqlSelectCols info expr@(EEntity ident) = ret
where where
process ed = uncommas $ process ed =
map ((name <>) . TLB.fromText) $ uncommas
entityColumnNames ed (fst info) $ map ((name <>) . TLB.fromText)
$ NEL.toList
$ keyAndEntityColumnNames ed (fst info)
-- 'name' is the biggest difference between 'RawSql' and -- 'name' is the biggest difference between 'RawSql' and
-- 'SqlSelect'. We automatically create names for tables -- 'SqlSelect'. We automatically create names for tables
-- (since it's not the user who's writing the FROM -- (since it's not the user who's writing the FROM

View File

@ -3,139 +3,142 @@
module Database.Esqueleto.Internal.PersistentImport module Database.Esqueleto.Internal.PersistentImport
-- NOTE: switch back to a module export once https://gitlab.haskell.org/ghc/ghc/merge_requests/276 -- NOTE: switch back to a module export once https://gitlab.haskell.org/ghc/ghc/merge_requests/276
-- has been merged. See https://github.com/bitemyapp/esqueleto/issues/110 for more details -- has been merged. See https://github.com/bitemyapp/esqueleto/issues/110 for more details
( toJsonText, ( toJsonText
entityIdFromJSON, , entityIdFromJSON
entityIdToJSON, , entityIdToJSON
entityValues, , entityValues
fromPersistValueJSON, , fromPersistValueJSON
keyValueEntityFromJSON, , keyValueEntityFromJSON
keyValueEntityToJSON, , keyValueEntityToJSON
toPersistValueJSON, , toPersistValueJSON
selectKeys, , selectKeys
belongsTo, , belongsTo
belongsToJust, , belongsToJust
getEntity, , getEntity
getJust, , getJust
getJustEntity, , getJustEntity
insertEntity, , insertEntity
insertRecord, , insertRecord
liftPersist, , liftPersist
checkUnique, , checkUnique
getByValue, , getByValue
insertBy, , insertBy
insertUniqueEntity, , insertUniqueEntity
onlyUnique, , onlyUnique
replaceUnique, , replaceUnique
transactionSave, , transactionSave
transactionUndo, , transactionUndo
defaultAttribute, , defaultAttribute
mkColumns, , mkColumns
getMigration, , getMigration
migrate, , migrate
parseMigration, , parseMigration
parseMigration', , parseMigration'
printMigration, , printMigration
runMigration, , runMigration
runMigrationSilent, , runMigrationSilent
runMigrationUnsafe, , runMigrationUnsafe
showMigration, , showMigration
decorateSQLWithLimitOffset, , decorateSQLWithLimitOffset
fieldDBName, , fieldDBName
fromSqlKey, , fromSqlKey
getFieldName, , getFieldName
getTableName, , getTableName
tableDBName, , tableDBName
toSqlKey, , toSqlKey
withRawQuery, , withRawQuery
getStmtConn, , getStmtConn
rawExecute, , rawExecute
rawExecuteCount, , rawExecuteCount
rawQuery, , rawQuery
rawQueryRes, , rawQueryRes
rawSql, , rawSql
close', , close'
createSqlPool, , createSqlPool
liftSqlPersistMPool, , liftSqlPersistMPool
runSqlConn, , runSqlConn
runSqlPersistM, , runSqlPersistM
runSqlPersistMPool, , runSqlPersistMPool
runSqlPool, , runSqlPool
withSqlConn, , withSqlConn
withSqlPool, , withSqlPool
readToUnknown, , readToUnknown
readToWrite, , readToWrite
writeToUnknown, , writeToUnknown
entityKeyFields, , getEntityKeyFields
entityPrimary, , entityPrimary
fromPersistValueText, , keyAndEntityFields
keyAndEntityFields, , PersistStore
toEmbedEntityDef, , PersistUnique
PersistStore, , DeleteCascade(..)
PersistUnique, , PersistConfig(..)
DeleteCascade(..), , BackendSpecificUpdate
PersistConfig(..), , Entity(..)
BackendSpecificUpdate, , PersistEntity(..)
Entity(..), , PersistField(..)
PersistEntity(..), , SomePersistField(..)
PersistField(..), , PersistQueryRead(..)
SomePersistField(..), , PersistQueryWrite(..)
PersistQueryRead(..), , BackendCompatible(..)
PersistQueryWrite(..), , BackendKey(..)
BackendCompatible(..), , HasPersistBackend(..)
BackendKey(..), , IsPersistBackend
HasPersistBackend(..), , PersistCore(..)
IsPersistBackend, , PersistRecordBackend
PersistCore(..), , PersistStoreRead(..)
PersistRecordBackend, , PersistStoreWrite(..)
PersistStoreRead(..), , ToBackendKey(..)
PersistStoreWrite(..), , PersistUniqueRead(..)
ToBackendKey(..), , PersistUniqueWrite(..)
PersistUniqueRead(..), , PersistFieldSql(..)
PersistUniqueWrite(..), , RawSql(..)
PersistFieldSql(..), , CautiousMigration
RawSql(..), , Column(..)
CautiousMigration, , ConnectionPool
Column(..), , Migration
ConnectionPool, , PersistentSqlException(..)
Migration, , Single(..)
PersistentSqlException(..), , Sql
Single(..), , SqlPersistM
Sql, , SqlPersistT
SqlPersistM, , InsertSqlResult(..)
SqlPersistT, , IsSqlBackend
InsertSqlResult(..), , LogFunc
IsSqlBackend, , SqlBackend
LogFunc, , SqlBackendCanRead
SqlBackend(..), , SqlBackendCanWrite
SqlBackendCanRead, , SqlReadBackend(..)
SqlBackendCanWrite, , SqlReadT
SqlReadBackend(..), , SqlWriteBackend(..)
SqlReadT, , SqlWriteT
SqlWriteBackend(..), , Statement(..)
SqlWriteT, , Attr
Statement(..), , Checkmark(..)
Attr, , CompositeDef(..)
Checkmark(..), , EmbedEntityDef(..)
CompositeDef(..), , EmbedFieldDef(..)
EmbedEntityDef(..), , EntityDef
EmbedFieldDef(..), , EntityIdDef(..)
EntityDef(..), , ExtraLine
ExtraLine, , FieldDef(..)
FieldDef(..), , FieldType(..)
FieldType(..), , ForeignDef(..)
ForeignDef(..), , ForeignFieldDef
ForeignFieldDef, , IsNullable(..)
IsNullable(..), , PersistException(..)
OnlyUniqueException(..), , PersistFilter(..)
PersistException(..), , PersistUpdate(..)
PersistFilter(..), , PersistValue(..)
PersistUpdate(..), , ReferenceDef(..)
PersistValue(..), , SqlType(..)
ReferenceDef(..), , UniqueDef(..)
SqlType(..), , UpdateException(..)
UniqueDef(..), , WhyNullable(..)
UpdateException(..), , getEntityFields
WhyNullable(..) , getEntityId
, getEntityDBName
, getEntityUniques
, getEntityDBName
) where ) where
import Database.Persist.Sql hiding import Database.Persist.Sql hiding
@ -148,6 +151,7 @@ import Database.Persist.Sql hiding
, delete , delete
, deleteCascadeWhere , deleteCascadeWhere
, deleteWhereCount , deleteWhereCount
, exists
, getPersistMap , getPersistMap
, limitOffsetOrder , limitOffsetOrder
, listToJSON , listToJSON
@ -171,5 +175,4 @@ import Database.Persist.Sql hiding
, (>.) , (>.)
, (>=.) , (>=.)
, (||.) , (||.)
, exists
) )

View File

@ -48,6 +48,7 @@ import Database.Esqueleto.Internal.Internal hiding (random_)
import Database.Esqueleto.Internal.PersistentImport hiding (upsert, upsertBy) import Database.Esqueleto.Internal.PersistentImport hiding (upsert, upsertBy)
import Database.Persist.Class (OnlyOneUniqueKey) import Database.Persist.Class (OnlyOneUniqueKey)
import Database.Persist (ConstraintNameDB(..), EntityNameDB(..)) import Database.Persist (ConstraintNameDB(..), EntityNameDB(..))
import Database.Persist.SqlBackend
-- | (@random()@) Split out into database specific modules -- | (@random()@) Split out into database specific modules
-- because MySQL uses `rand()`. -- because MySQL uses `rand()`.
@ -207,7 +208,7 @@ upsertBy
-- ^ the record in the database after the operation -- ^ the record in the database after the operation
upsertBy uniqueKey record updates = do upsertBy uniqueKey record updates = do
sqlB <- R.ask sqlB <- R.ask
case connUpsertSql sqlB of case getConnUpsertSql sqlB of
Nothing -> Nothing ->
-- Postgres backend should have connUpsertSql, if this error is -- Postgres backend should have connUpsertSql, if this error is
-- thrown, check changes on persistent -- thrown, check changes on persistent
@ -219,7 +220,7 @@ upsertBy uniqueKey record updates = do
entDef = entityDef (Just record) entDef = entityDef (Just record)
updatesText conn = first builderToText $ renderUpdates conn updates updatesText conn = first builderToText $ renderUpdates conn updates
#if MIN_VERSION_persistent(2,11,0) #if MIN_VERSION_persistent(2,11,0)
uniqueFields = NonEmpty.fromList (persistUniqueToFieldNames uniqueKey) uniqueFields = persistUniqueToFieldNames uniqueKey
handler sqlB upsertSql = do handler sqlB upsertSql = do
let (updateText, updateVals) = let (updateText, updateVals) =
updatesText sqlB updatesText sqlB
@ -307,7 +308,7 @@ insertSelectWithConflictCount unique query conflictQuery = do
updates = conflictQuery entCurrent entExcluded updates = conflictQuery entCurrent entExcluded
combine (tlb1,vals1) (tlb2,vals2) = (builderToText (tlb1 `mappend` tlb2), vals1 ++ vals2) combine (tlb1,vals1) (tlb2,vals2) = (builderToText (tlb1 `mappend` tlb2), vals1 ++ vals2)
entExcluded = EEntity $ I "excluded" entExcluded = EEntity $ I "excluded"
tableName = unEntityNameDB . entityDB . entityDef tableName = unEntityNameDB . getEntityDBName . entityDef
entCurrent = EEntity $ I (tableName proxy) entCurrent = EEntity $ I (tableName proxy)
uniqueDef = toUniqueDef unique uniqueDef = toUniqueDef unique
constraint = TLB.fromText . unConstraintNameDB . uniqueDBName $ uniqueDef constraint = TLB.fromText . unConstraintNameDB . uniqueDBName $ uniqueDef

12
stack-8.10.yaml Normal file
View File

@ -0,0 +1,12 @@
resolver: lts-17.8
packages:
- '.'
- 'examples'
extra-deps:
- lift-type-0.1.0.1
- persistent-2.13.0.0
- persistent-sqlite-2.13.0.0
- persistent-mysql-2.13.0.0
- persistent-postgresql-2.13.0.0

View File

@ -1,4 +1,4 @@
resolver: lts-17.8 resolver: lts-16.31
packages: packages:
- '.' - '.'

View File

@ -1,4 +1,6 @@
resolver: nightly-2020-09-20 resolver: nightly-2021-05-05
packages: packages:
- '.' - '.'
- 'examples' - 'examples'

View File

@ -6,7 +6,7 @@
packages: [] packages: []
snapshots: snapshots:
- completed: - completed:
size: 467884 size: 581922
url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/nightly/2020/1/24.yaml url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/nightly/2021/5/5.yaml
sha256: 55c1a4fc9222bc3b8cf91461f38e2641da675a7296f06528f47340c19d0c6e85 sha256: 70797737e072284037792abaffd399e029da7ec3c855fd27b16898662f285d82
original: nightly-2020-01-24 original: nightly-2021-05-05

View File

@ -1 +1 @@
stack-8.8.yaml stack-8.10.yaml

View File

@ -161,10 +161,6 @@ testSqliteTextFunctions = do
nameContains like "i" [p4e, p3e] nameContains like "i" [p4e, p3e]
nameContains like "iv" [p4e] nameContains like "iv" [p4e]
main :: IO () main :: IO ()
main = do main = do
hspec $ do hspec $ do
@ -173,7 +169,7 @@ main = do
describe "Test SQLite locking" $ do describe "Test SQLite locking" $ do
testLocking withConn testLocking withConn
describe "SQLite specific tests" $ do fdescribe "SQLite specific tests" $ do
testAscRandom random_ run testAscRandom random_ run
testRandomMath run testRandomMath run
testSqliteRandom testSqliteRandom
@ -184,10 +180,6 @@ main = do
testSqliteUpdate testSqliteUpdate
testSqliteTextFunctions testSqliteTextFunctions
run, runSilent, runVerbose :: Run run, runSilent, runVerbose :: Run
runSilent act = runNoLoggingT $ run_worker act runSilent act = runNoLoggingT $ run_worker act
runVerbose act = runStderrLoggingT $ run_worker act runVerbose act = runStderrLoggingT $ run_worker act
@ -196,20 +188,16 @@ run =
then runVerbose then runVerbose
else runSilent else runSilent
verbose :: Bool verbose :: Bool
verbose = False verbose = False
run_worker :: RunDbMonad m => SqlPersistT (R.ResourceT m) a -> m a run_worker :: RunDbMonad m => SqlPersistT (R.ResourceT m) a -> m a
run_worker act = withConn $ runSqlConn (migrateIt >> act) run_worker act = withConn $ runSqlConn (migrateIt >> act)
migrateIt :: RunDbMonad m => SqlPersistT (R.ResourceT m) () migrateIt :: RunDbMonad m => SqlPersistT (R.ResourceT m) ()
migrateIt = do migrateIt = do
void $ runMigrationSilent migrateAll void $ runMigrationSilent migrateAll
withConn :: RunDbMonad m => (SqlBackend -> R.ResourceT m a) -> m a withConn :: RunDbMonad m => (SqlBackend -> R.ResourceT m a) -> m a
withConn = withConn =
R.runResourceT . withSqliteConn ":memory:" R.runResourceT . withSqliteConn ":memory:"