From 816b86dcdc98c3e783b534a285c657698ace1252 Mon Sep 17 00:00:00 2001 From: Brandon Chinn Date: Tue, 24 Nov 2020 13:48:30 -0800 Subject: [PATCH] Add script to generate code --- package.yaml | 1 + persistent-mtl.cabal | 3 +- scripts/generate/GeneratePersistentAPI.hs | 145 +++++ scripts/generate/README.md | 53 ++ scripts/generate/persistent-api.yaml | 546 ++++++++++++++++++ scripts/generate/run.sh | 4 + scripts/generate/templates/Shim.mustache | 27 + .../generate/templates/SqlQueryRep.mustache | 50 ++ src/Database/Persist/Monad/Shim.hs | 338 ++++++++++- src/Database/Persist/Monad/SqlQueryRep.hs | 380 ++++++++++-- 10 files changed, 1486 insertions(+), 61 deletions(-) create mode 100755 scripts/generate/GeneratePersistentAPI.hs create mode 100644 scripts/generate/README.md create mode 100644 scripts/generate/persistent-api.yaml create mode 100755 scripts/generate/run.sh create mode 100644 scripts/generate/templates/Shim.mustache create mode 100644 scripts/generate/templates/SqlQueryRep.mustache diff --git a/package.yaml b/package.yaml index cb0ddb9..a0997dd 100644 --- a/package.yaml +++ b/package.yaml @@ -8,6 +8,7 @@ library: source-dirs: src dependencies: - base >= 4.10 && < 5 + - conduit >= 1.3.0.3 && < 2 - containers >= 0.5.10.2 && < 0.7 - mtl >= 2.2.2 && < 3 - persistent >= 2.8.2 && < 3 diff --git a/persistent-mtl.cabal b/persistent-mtl.cabal index 0e70027..3af9ab0 100644 --- a/persistent-mtl.cabal +++ b/persistent-mtl.cabal @@ -4,7 +4,7 @@ cabal-version: 1.12 -- -- see: https://github.com/sol/hpack -- --- hash: f1717fb11c2c334c4fb635d2ab3fafd4960e5d56d9f998a53962019736a970e5 +-- hash: ccffc525bb8ea958adc029c2843acb2d57cdde2da16fdefa077abe546000ab44 name: persistent-mtl version: 0.1.0.0 @@ -25,6 +25,7 @@ library ghc-options: -Wall build-depends: base >=4.10 && <5 + , conduit >=1.3.0.3 && <2 , containers >=0.5.10.2 && <0.7 , mtl >=2.2.2 && <3 , persistent >=2.8.2 && <3 diff --git a/scripts/generate/GeneratePersistentAPI.hs b/scripts/generate/GeneratePersistentAPI.hs new file mode 100755 index 0000000..933a992 --- /dev/null +++ b/scripts/generate/GeneratePersistentAPI.hs @@ -0,0 +1,145 @@ +{- + stack script --resolver lts-16.23 + --package aeson + --package containers + --package mustache + --package text + --package unliftio + --package yaml +-} + +{-# LANGUAGE DuplicateRecordFields #-} +{-# LANGUAGE OverloadedStrings #-} +{-# LANGUAGE RecordWildCards #-} + +import Control.Monad (forM_) +import Data.Aeson (FromJSON(..), withObject, (.!=), (.:), (.:?)) +import Data.Char (isAlphaNum, toUpper) +import Data.List (nub, sort) +import Data.Map (Map) +import Data.Text (Text) +import qualified Data.Text as Text +import qualified Data.Text.IO as Text +import qualified Data.Yaml as Yaml +import Text.Mustache (ToMustache(..), object, (~>)) +import qualified Text.Mustache as Mustache +import qualified Text.Mustache.Types as Mustache + +{- Configuration -} + +-- | See `README.md` for a description of this data type. +data PersistentFunction = PersistentFunction + { name :: Text + , constraints :: [Text] + , args :: [Text] + , result :: Text + } deriving (Show) + +instance FromJSON PersistentFunction where + parseJSON = withObject "PersistentFunction" $ \o -> + PersistentFunction + <$> o .: "name" + <*> o .:? "constraints" .!= [] + <*> o .:? "args" .!= [] + <*> o .: "result" + +{- Rendering -} + +data Context = Context + { functions :: [FunctionContext] + } + +instance ToMustache Context where + toMustache Context{..} = object [ "functions" ~> functions ] + +buildContext :: [PersistentFunction] -> Context +buildContext = Context . map buildFunctionContext + +data FunctionContext = FunctionContext + { name :: Text + , constraints :: [Text] + , args :: [Text] + , result :: Text + } + +buildFunctionContext :: PersistentFunction -> FunctionContext +buildFunctionContext PersistentFunction{..} = FunctionContext{..} + +instance ToMustache FunctionContext where + toMustache FunctionContext{..} = object + [ "name" ~> name + , "nameCapital" ~> capitalize name + , "constraints" ~> enumerateWith fromConstraint constraints + , "args" ~> enumerateWith fromArg args + , "result" ~> result + , "sqlQueryRepRecord" ~> sqlQueryRepRecord + , "recordTypeVars" ~> recordTypeVars + ] + where + fromConstraint constraint = object [ "type" ~> constraint ] + fromArg arg = object [ "type" ~> arg ] + recordTypeVars = getRecordTypeVars constraints + + -- the `record` type variable for SqlQueryRep + sqlQueryRepRecord = case recordTypeVars of + [] -> "Void" + [record] -> record + records -> "(" <> Text.intercalate ", " records <> ")" + +-- | Get all `record` type variables in the given list of constraints. +-- +-- A type variable is considered a `record` type variable if it matches the +-- pattern "record|recordN", where `N` is a number. The type variables will +-- be sorted when returned. +-- +-- e.g. +-- ["Foo record"] -> ["record"] +-- ["Bar record1", "Foo record2 record1"] -> ["record1", "record2"] +getRecordTypeVars :: [Text] -> [Text] +getRecordTypeVars = sort . nub . concatMap getPersistRecordsIn + where + getPersistRecordsIn = filter ("record" `Text.isPrefixOf`) . Text.words . ignoreNonAlphaNum + ignoreNonAlphaNum = Text.map (\c -> if isAlphaNum c then c else ' ') + +capitalize :: Text -> Text +capitalize t = case Text.uncons t of + Just (c, cs) -> Text.cons (toUpper c) cs + Nothing -> t + +-- | Convert each element in the list into a Value with the given function, +-- adding the "index" and "last" keys indicating the element's index in the list +-- and whether the element is the last one in the list, respectively. +enumerateWith :: (a -> Mustache.Value) -> [a] -> [Mustache.Value] +enumerateWith f xs = + let mkElem x i = merge (f x) $ object + [ "index" ~> i + , "last" ~> (i == length xs) + ] + in zipWith mkElem xs [1..] + +-- If only Value had a Monoid instance... +merge :: Mustache.Value -> Mustache.Value -> Mustache.Value +merge (Mustache.Object o1) (Mustache.Object o2) = Mustache.Object $ o1 <> o2 +merge v _ = v + +{- Main -} + +main :: IO () +main = do + context <- buildContext <$> Yaml.decodeFileThrow "persistent-api.yaml" + + generate "SqlQueryRep.mustache" "Database/Persist/Monad/SqlQueryRep.hs" context + generate "Shim.mustache" "Database/Persist/Monad/Shim.hs" context + +srcDir :: FilePath +srcDir = "../../src/" + +generate :: ToMustache k => FilePath -> FilePath -> k -> IO () +generate templatePath output value = do + template <- either (error . show) return =<< Mustache.automaticCompile ["./templates"] templatePath + case Mustache.checkedSubstitute template value of + ([], rendered) -> Text.writeFile (srcDir ++ output) rendered + (errors, _) -> error $ unlines $ + "Found errors when generating template:" : map showError errors + where + showError e = "* " ++ show e diff --git a/scripts/generate/README.md b/scripts/generate/README.md new file mode 100644 index 0000000..b8c379b --- /dev/null +++ b/scripts/generate/README.md @@ -0,0 +1,53 @@ +# Generating lifted persistent functions + +## Usage + +``` +scripts/generate/run.sh +``` + +## Configuration + +Configuration lives in `persistent-api.yaml`. The file contains a list of objects, where each object corresponds to a `persistent` function that we want to lift into the `MonadSqlQuery` context. Follow the instructions in this guide to update the YAML file, which will generate the appropriate Haskell code. If you're trying to add a function that doesn't fit neatly with the instructions or categories, bring up a discussion with other developers. + +To add a function, write down its type then do the following: + +1. Update type variables + * Specialize `backend` as `SqlBackend` + * Ensure the `PersistEntity` type variable is named `record`. If there are multiple `PersistEntity` types, they should be named `record1`, `record2`, etc. Choose an order that makes sense for `withRecord`, e.g. + + ```hs + withRecord @(record1, record2, ...) $ ... + ``` + +1. Simplify constraints + * Remove redundant constraints, e.g. `PersistQueryRead SqlBackend` + * Substitute `PersistRecordBackend`, if applicable + +1. Look at the monad type(s) in the function: + 1. If there are multiple monad types, go to the "Advanced" section + 1. If the monad has a constraint other than `Monad`, `MonadIO`, or `MonadUnliftIO`, go to the "Advanced" section + 1. Otherwise, go to the "Basic" section + +### Basic + +First, make the following modifications: + +1. Ensure the monad type variable is named `m` +1. Remove all `Monad`, `MonadIO`, and `MonadUnliftIO` constraints + * At this point, the monad shouldn't have any constraints +1. Rename `ReaderT SqlBackend m a` as `m a` + +Then add the function to the YAML file in the following format: + +* `name`: The function's name +* `constraints`: The function's constraints +* `args`: The function's arguments +* `result`: The function's result, without the monad + * e.g. a function that returns `m (Maybe Foo)` should have `result` set to just `(Maybe Foo)` + +There should be no references to `m` here. + +### Advanced + +TODO diff --git a/scripts/generate/persistent-api.yaml b/scripts/generate/persistent-api.yaml new file mode 100644 index 0000000..271ef72 --- /dev/null +++ b/scripts/generate/persistent-api.yaml @@ -0,0 +1,546 @@ +# PersistStoreRead + +- name: get + constraints: + - 'PersistRecordBackend record SqlBackend' + args: + - 'Key record' + result: '(Maybe record)' + +- name: getMany + constraints: + - 'PersistRecordBackend record SqlBackend' + args: + - '[Key record]' + result: '(Map (Key record) record)' + +- name: getJust + constraints: + - 'PersistRecordBackend record SqlBackend' + args: + - 'Key record' + result: 'record' + +- name: getJustEntity + constraints: + - 'PersistRecordBackend record SqlBackend' + args: + - 'Key record' + result: '(Entity record)' + +- name: getEntity + constraints: + - 'PersistRecordBackend record SqlBackend' + args: + - 'Key record' + result: '(Maybe (Entity record))' + +- name: belongsTo + constraints: + - 'PersistEntity record1' + - 'PersistRecordBackend record2 SqlBackend' + args: + - '(record1 -> Maybe (Key record2))' + - 'record1' + result: '(Maybe record2)' + +- name: belongsToJust + constraints: + - 'PersistEntity record1' + - 'PersistRecordBackend record2 SqlBackend' + args: + - '(record1 -> Key record2)' + - 'record1' + result: 'record2' + +# PersistStoreWrite + +- name: insert + constraints: + - 'PersistRecordBackend record SqlBackend' + args: + - 'record' + result: '(Key record)' + +- name: insert_ + constraints: + - 'PersistRecordBackend record SqlBackend' + args: + - 'record' + result: '()' + +- name: insertMany + constraints: + - 'PersistRecordBackend record SqlBackend' + args: + - '[record]' + result: '[Key record]' + +- name: insertMany_ + constraints: + - 'PersistRecordBackend record SqlBackend' + args: + - '[record]' + result: '()' + +- name: insertEntityMany + constraints: + - 'PersistRecordBackend record SqlBackend' + args: + - '[Entity record]' + result: '()' + +- name: insertKey + constraints: + - 'PersistRecordBackend record SqlBackend' + args: + - 'Key record' + - 'record' + result: '()' + +- name: repsert + constraints: + - 'PersistRecordBackend record SqlBackend' + args: + - 'Key record' + - 'record' + result: '()' + +- name: repsertMany + constraints: + - 'PersistRecordBackend record SqlBackend' + args: + - '[(Key record, record)]' + result: '()' + +- name: replace + constraints: + - 'PersistRecordBackend record SqlBackend' + args: + - 'Key record' + - 'record' + result: '()' + +- name: delete + constraints: + - 'PersistRecordBackend record SqlBackend' + args: + - 'Key record' + result: '()' + +- name: update + constraints: + - 'PersistRecordBackend record SqlBackend' + args: + - 'Key record' + - '[Update record]' + result: '()' + +- name: updateGet + constraints: + - 'PersistRecordBackend record SqlBackend' + args: + - 'Key record' + - '[Update record]' + result: 'record' + +- name: insertEntity + constraints: + - 'PersistRecordBackend record SqlBackend' + args: + - 'record' + result: '(Entity record)' + +- name: insertRecord + constraints: + - 'PersistRecordBackend record SqlBackend' + args: + - 'record' + result: 'record' + +# PersistUniqueRead + +- name: getBy + constraints: + - 'PersistRecordBackend record SqlBackend' + args: + - 'Unique record' + result: '(Maybe (Entity record))' + +- name: getByValue + constraints: + - 'PersistRecordBackend record SqlBackend' + - 'AtLeastOneUniqueKey record' + args: + - 'record' + result: '(Maybe (Entity record))' + +- name: checkUnique + constraints: + - 'PersistRecordBackend record SqlBackend' + args: + - 'record' + result: '(Maybe (Unique record))' + +# TODO: >= 2.11 +# - name: checkUniqueUpdateable +# constraints: +# - 'PersistRecordBackend record SqlBackend' +# args: +# - 'Entity record' +# result: '(Maybe (Unique record))' + +# PersistUniqueWrite + +- name: deleteBy + constraints: + - 'PersistRecordBackend record SqlBackend' + args: + - 'Unique record' + result: '()' + +- name: insertUnique + constraints: + - 'PersistRecordBackend record SqlBackend' + args: + - 'record' + result: '(Maybe (Key record))' + +- name: upsert + constraints: + - 'PersistRecordBackend record SqlBackend' + - 'OnlyOneUniqueKey record' + args: + - 'record' + - '[Update record]' + result: '(Entity record)' + +- name: upsertBy + constraints: + - 'PersistRecordBackend record SqlBackend' + args: + - 'Unique record' + - 'record' + - '[Update record]' + result: '(Entity record)' + +- name: putMany + constraints: + - 'PersistRecordBackend record SqlBackend' + args: + - '[record]' + result: '()' + +- name: insertBy + constraints: + - 'PersistRecordBackend record SqlBackend' + - 'AtLeastOneUniqueKey record' + args: + - 'record' + result: '(Either (Entity record) (Key record))' + +- name: insertUniqueEntity + constraints: + - 'PersistRecordBackend record SqlBackend' + args: + - 'record' + result: '(Maybe (Entity record))' + +- name: replaceUnique + constraints: + - 'PersistRecordBackend record SqlBackend' + - 'Eq (Unique record)' + args: + - 'Key record' + - 'record' + result: '(Maybe (Unique record))' + +- name: onlyUnique + constraints: + - 'PersistRecordBackend record SqlBackend' + - 'OnlyOneUniqueKey record' + args: + - 'record' + result: '(Unique record)' + +# PersistQueryRead + +# TODO: advanced +# - name: selectSourceRes +# constraints: +# - 'MonadIO m1' +# - 'MonadIO m2' +# - 'PersistRecordBackend record SqlBackend' +# args: +# - '[Filter record]' +# - '[SelectOpt record]' +# result: 'm1 (Acquire (ConduitM () (Entity record) m2 ()))' + +- name: selectFirst + constraints: + - 'PersistRecordBackend record SqlBackend' + args: + - '[Filter record]' + - '[SelectOpt record]' + result: '(Maybe (Entity record))' + +# TODO: advanced +# - name: selectKeysRes +# constraints: +# - 'MonadIO m1' +# - 'MonadIO m2' +# - 'PersistRecordBackend record SqlBackend' +# args: +# - '[Filter record]' +# - '[SelectOpt record]' +# result: 'm1 (Acquire (ConduitM () (Key record) m2 ()))' + +- name: count + constraints: + - 'PersistRecordBackend record SqlBackend' + args: + - '[Filter record]' + result: 'Int' + +# TODO: >= 2.11 +# - name: exists +# constraints: +# - 'PersistRecordBackend record SqlBackend' +# args: +# - '[Filter record]' +# result: 'Bool' + +# TODO: advanced +# - name: selectSource +# constraints: +# - 'MonadResource m' +# - 'PersistRecordBackend record SqlBackend' +# - 'MonadReader SqlBackend m' +# args: +# - '[Filter record]' +# - '[SelectOpt record]' +# result: 'ConduitM () (Entity record) m ()' + +# TODO: advanced +# - name: selectKeys +# constraints: +# - 'MonadResource m' +# - 'PersistRecordBackend record SqlBackend' +# - 'MonadReader SqlBackend m' +# args: +# - '[Filter record]' +# - '[SelectOpt record]' +# result: 'ConduitM () (Key record) m ()' + +- name: selectList + constraints: + - 'PersistRecordBackend record SqlBackend' + args: + - '[Filter record]' + - '[SelectOpt record]' + result: '[Entity record]' + +- name: selectKeysList + constraints: + - 'PersistRecordBackend record SqlBackend' + args: + - '[Filter record]' + - '[SelectOpt record]' + result: '[Key record]' + +# PersistQueryWrite + +- name: updateWhere + constraints: + - 'PersistRecordBackend record SqlBackend' + args: + - '[Filter record]' + - '[Update record]' + result: '()' + +- name: deleteWhere + constraints: + - 'PersistRecordBackend record SqlBackend' + args: + - '[Filter record]' + result: '()' + +- name: deleteWhereCount + constraints: + - 'PersistRecordBackend record SqlBackend' + args: + - '[Filter record]' + result: 'Int64' + +- name: updateWhereCount + constraints: + - 'PersistRecordBackend record SqlBackend' + args: + - '[Filter record]' + - '[Update record]' + result: 'Int64' + +# DeleteCascade + +- name: deleteCascade + constraints: + - 'DeleteCascade record SqlBackend' + args: + - 'Key record' + result: '()' + +- name: deleteCascadeWhere + constraints: + - 'DeleteCascade record SqlBackend' + args: + - '[Filter record]' + result: '()' + +# migration + +- name: parseMigration + constraints: + - 'HasCallStack' + args: + - 'Migration' + result: '(Either [Text] CautiousMigration)' + +- name: parseMigration' + constraints: + - 'HasCallStack' + args: + - 'Migration' + result: 'CautiousMigration' + +- name: printMigration + constraints: + - 'HasCallStack' + args: + - 'Migration' + result: '()' + +- name: showMigration + constraints: + - 'HasCallStack' + args: + - 'Migration' + result: '[Text]' + +- name: getMigration + constraints: + - 'HasCallStack' + args: + - 'Migration' + result: '[Sql]' + +- name: runMigration + args: + - 'Migration' + result: '()' + +- name: runMigrationQuiet + args: + - 'Migration' + result: '[Text]' + +- name: runMigrationSilent + args: + - 'Migration' + result: '[Text]' + +- name: runMigrationUnsafe + args: + - 'Migration' + result: '()' + +- name: runMigrationUnsafeQuiet + constraints: + - 'HasCallStack' + args: + - 'Migration' + result: '[Text]' + +# database identifiers + +- name: getFieldName + constraints: + - 'PersistRecordBackend record SqlBackend' + args: + - 'EntityField record typ' + result: 'Text' + +- name: getTableName + constraints: + - 'PersistEntity record' + args: + - 'record' + result: 'Text' + +# raw queries + +- name: withRawQuery + args: + - 'Text' + - '[PersistValue]' + - 'ConduitM [PersistValue] Void IO a' + result: 'a' + +# TODO: advanced +# - name: rawQueryRes +# constraints: +# - 'MonadIO m1' +# - 'MonadIO m2' +# - 'BackendCompatible SqlBackend env' +# args: +# - 'Text' +# - '[PersistValue]' +# result: 'ReaderT env m1 (Acquire (ConduitM () [PersistValue] m2 ()))' + +# TODO: advanced +# - name: rawQuery +# constraints: +# - 'MonadResource m' +# - 'MonadReader env m' +# - 'BackendCompatible SqlBackend env' +# args: +# - 'Text' +# - '[PersistValue]' +# result: 'ConduitM () [PersistValue] m ()' + +- name: rawExecute + args: + - 'Text' + - '[PersistValue]' + result: '()' + +- name: rawExecuteCount + args: + - 'Text' + - '[PersistValue]' + result: 'Int64' + +- name: rawSql + constraints: + - 'RawSql a' + args: + - 'Text' + - '[PersistValue]' + result: '[a]' + +# transactions + +- name: transactionSave + result: '()' + +- name: transactionSaveWithIsolation + args: + - 'IsolationLevel' + result: '()' + +- name: transactionUndo + result: '()' + +- name: transactionUndoWithIsolation + args: + - 'IsolationLevel' + result: '()' diff --git a/scripts/generate/run.sh b/scripts/generate/run.sh new file mode 100755 index 0000000..10c95ff --- /dev/null +++ b/scripts/generate/run.sh @@ -0,0 +1,4 @@ +#!/usr/bin/env bash + +cd "$(dirname "${BASH_SOURCE[0]}")" +exec stack GeneratePersistentAPI.hs diff --git a/scripts/generate/templates/Shim.mustache b/scripts/generate/templates/Shim.mustache new file mode 100644 index 0000000..2bb5442 --- /dev/null +++ b/scripts/generate/templates/Shim.mustache @@ -0,0 +1,27 @@ +{-# LANGUAGE FlexibleContexts #-} +{-# LANGUAGE GADTs #-} +{-# LANGUAGE PatternSynonyms #-} + +module Database.Persist.Monad.Shim where + +import Data.Conduit (ConduitM) +import Data.Int (Int64) +import Data.Map (Map) +import Data.Text (Text) +import Data.Typeable (Typeable) +import Data.Void (Void) +import Database.Persist.Sql hiding (pattern Update) +import GHC.Stack (HasCallStack) + +import Database.Persist.Monad.Class (MonadSqlQuery(..)) +import Database.Persist.Monad.SqlQueryRep (SqlQueryRep(..)) + +{-# ANN module "HLint: ignore" #-} + +{{#functions}} +{{{name}}} + :: ({{#constraints}}{{{type}}}, {{/constraints}}{{#recordTypeVars}}Typeable {{.}}, {{/recordTypeVars}}MonadSqlQuery m) + => {{#args}}{{{type}}} -> {{/args}}m {{result}} +{{{name}}} {{#args}}a{{index}} {{/args}}= runQueryRep $ {{{nameCapital}}}{{#args}} a{{index}}{{/args}} + +{{/functions}} diff --git a/scripts/generate/templates/SqlQueryRep.mustache b/scripts/generate/templates/SqlQueryRep.mustache new file mode 100644 index 0000000..409b63c --- /dev/null +++ b/scripts/generate/templates/SqlQueryRep.mustache @@ -0,0 +1,50 @@ +{-# LANGUAGE FlexibleContexts #-} +{-# LANGUAGE GADTs #-} +{-# LANGUAGE LambdaCase #-} +{-# LANGUAGE PatternSynonyms #-} +{-# LANGUAGE ScopedTypeVariables #-} +{-# LANGUAGE TypeApplications #-} + +module Database.Persist.Monad.SqlQueryRep + ( SqlQueryRep(..) + , runSqlQueryRep + ) where + +import Control.Monad.IO.Unlift (MonadUnliftIO) +import Data.Conduit (ConduitM) +import Data.Int (Int64) +import Data.Map (Map) +import Data.Proxy (Proxy(..)) +import Data.Text (Text) +import Data.Typeable (Typeable, eqT, typeRep, (:~:)(..)) +import Data.Void (Void) +import Database.Persist.Sql as Persist hiding (pattern Update) +import GHC.Stack (HasCallStack) + +{-# ANN module "HLint: ignore" #-} + +data SqlQueryRep record a where +{{#functions}} + {{{nameCapital}}} + :: ({{#constraints}}{{{type}}}{{^last}}, {{/last}}{{/constraints}}) + => {{#args}}{{{type}}} -> {{/args}}SqlQueryRep {{sqlQueryRepRecord}} {{result}} + +{{/functions}} +instance Typeable record => Show (SqlQueryRep record a) where + show = \case +{{#functions}} + {{{nameCapital}}}{} -> "{{{nameCapital}}}{..}" ++ record +{{/functions}} + where + record = case recordTypeRep of + Just recordType -> "<" ++ show recordType ++ ">" + Nothing -> "" + recordTypeRep = case eqT @record @Void of + Just Refl -> Nothing + Nothing -> Just $ typeRep $ Proxy @record + +runSqlQueryRep :: MonadUnliftIO m => SqlQueryRep record a -> Persist.SqlPersistT m a +runSqlQueryRep = \case +{{#functions}} + {{{nameCapital}}} {{#args}}a{{index}} {{/args}}-> Persist.{{{name}}}{{#args}} a{{index}}{{/args}} +{{/functions}} diff --git a/src/Database/Persist/Monad/Shim.hs b/src/Database/Persist/Monad/Shim.hs index 954dd0b..97028a9 100644 --- a/src/Database/Persist/Monad/Shim.hs +++ b/src/Database/Persist/Monad/Shim.hs @@ -1,50 +1,334 @@ +{-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE GADTs #-} +{-# LANGUAGE PatternSynonyms #-} module Database.Persist.Monad.Shim where -import Control.Monad.IO.Unlift (MonadUnliftIO) +import Data.Conduit (ConduitM) +import Data.Int (Int64) import Data.Map (Map) import Data.Text (Text) import Data.Typeable (Typeable) -import Database.Persist -import Database.Persist.Sql +import Data.Void (Void) +import Database.Persist.Sql hiding (pattern Update) +import GHC.Stack (HasCallStack) import Database.Persist.Monad.Class (MonadSqlQuery(..)) import Database.Persist.Monad.SqlQueryRep (SqlQueryRep(..)) -{- PersistStoreRead -} +{-# ANN module "HLint: ignore" #-} -get :: (PersistRecordBackend record SqlBackend, Typeable record, MonadSqlQuery m) => Key record -> m (Maybe record) -get a = runQueryRep $ Get a +get + :: (PersistRecordBackend record SqlBackend, Typeable record, MonadSqlQuery m) + => Key record -> m (Maybe record) +get a1 = runQueryRep $ Get a1 -getMany :: (PersistRecordBackend record SqlBackend, Typeable record, MonadSqlQuery m) => [Key record] -> m (Map (Key record) record) -getMany a = runQueryRep $ GetMany a +getMany + :: (PersistRecordBackend record SqlBackend, Typeable record, MonadSqlQuery m) + => [Key record] -> m (Map (Key record) record) +getMany a1 = runQueryRep $ GetMany a1 -getJust :: (PersistRecordBackend record SqlBackend, Typeable record, MonadSqlQuery m) => Key record -> m record -getJust a = runQueryRep $ GetJust a +getJust + :: (PersistRecordBackend record SqlBackend, Typeable record, MonadSqlQuery m) + => Key record -> m record +getJust a1 = runQueryRep $ GetJust a1 -getJustEntity :: (PersistRecordBackend record SqlBackend, Typeable record, MonadSqlQuery m) => Key record -> m (Entity record) -getJustEntity a = runQueryRep $ GetJustEntity a +getJustEntity + :: (PersistRecordBackend record SqlBackend, Typeable record, MonadSqlQuery m) + => Key record -> m (Entity record) +getJustEntity a1 = runQueryRep $ GetJustEntity a1 -getEntity :: (PersistRecordBackend record SqlBackend, Typeable record, MonadSqlQuery m) => Key record -> m (Maybe (Entity record)) -getEntity a = runQueryRep $ GetEntity a +getEntity + :: (PersistRecordBackend record SqlBackend, Typeable record, MonadSqlQuery m) + => Key record -> m (Maybe (Entity record)) +getEntity a1 = runQueryRep $ GetEntity a1 -belongsTo :: (PersistEntity record1, PersistRecordBackend record2 SqlBackend, Typeable record1, Typeable record2, MonadSqlQuery m) => (record1 -> Maybe (Key record2)) -> record1 -> m (Maybe record2) -belongsTo a b = runQueryRep $ BelongsTo a b +belongsTo + :: (PersistEntity record1, PersistRecordBackend record2 SqlBackend, Typeable record1, Typeable record2, MonadSqlQuery m) + => (record1 -> Maybe (Key record2)) -> record1 -> m (Maybe record2) +belongsTo a1 a2 = runQueryRep $ BelongsTo a1 a2 -belongsToJust :: (PersistEntity record1, PersistRecordBackend record2 SqlBackend, Typeable record1, Typeable record2, MonadSqlQuery m) => (record1 -> Key record2) -> record1 -> m record2 -belongsToJust a b = runQueryRep $ BelongsToJust a b +belongsToJust + :: (PersistEntity record1, PersistRecordBackend record2 SqlBackend, Typeable record1, Typeable record2, MonadSqlQuery m) + => (record1 -> Key record2) -> record1 -> m record2 +belongsToJust a1 a2 = runQueryRep $ BelongsToJust a1 a2 -{- Other -} +insert + :: (PersistRecordBackend record SqlBackend, Typeable record, MonadSqlQuery m) + => record -> m (Key record) +insert a1 = runQueryRep $ Insert a1 -selectList :: (PersistRecordBackend record SqlBackend, Typeable record, MonadSqlQuery m) => [Filter record] -> [SelectOpt record] -> m [Entity record] -selectList a b = runQueryRep $ SelectList a b +insert_ + :: (PersistRecordBackend record SqlBackend, Typeable record, MonadSqlQuery m) + => record -> m () +insert_ a1 = runQueryRep $ Insert_ a1 -insert :: (PersistRecordBackend record SqlBackend, Typeable record, MonadSqlQuery m) => record -> m (Key record) -insert a = runQueryRep $ Insert a +insertMany + :: (PersistRecordBackend record SqlBackend, Typeable record, MonadSqlQuery m) + => [record] -> m [Key record] +insertMany a1 = runQueryRep $ InsertMany a1 -insert_ :: (PersistRecordBackend record SqlBackend, Typeable record, MonadSqlQuery m) => record -> m () -insert_ a = runQueryRep $ Insert_ a +insertMany_ + :: (PersistRecordBackend record SqlBackend, Typeable record, MonadSqlQuery m) + => [record] -> m () +insertMany_ a1 = runQueryRep $ InsertMany_ a1 -runMigrationSilent :: (MonadUnliftIO m, MonadSqlQuery m) => Migration -> m [Text] -runMigrationSilent a = runQueryRep $ RunMigrationsSilent a +insertEntityMany + :: (PersistRecordBackend record SqlBackend, Typeable record, MonadSqlQuery m) + => [Entity record] -> m () +insertEntityMany a1 = runQueryRep $ InsertEntityMany a1 + +insertKey + :: (PersistRecordBackend record SqlBackend, Typeable record, MonadSqlQuery m) + => Key record -> record -> m () +insertKey a1 a2 = runQueryRep $ InsertKey a1 a2 + +repsert + :: (PersistRecordBackend record SqlBackend, Typeable record, MonadSqlQuery m) + => Key record -> record -> m () +repsert a1 a2 = runQueryRep $ Repsert a1 a2 + +repsertMany + :: (PersistRecordBackend record SqlBackend, Typeable record, MonadSqlQuery m) + => [(Key record, record)] -> m () +repsertMany a1 = runQueryRep $ RepsertMany a1 + +replace + :: (PersistRecordBackend record SqlBackend, Typeable record, MonadSqlQuery m) + => Key record -> record -> m () +replace a1 a2 = runQueryRep $ Replace a1 a2 + +delete + :: (PersistRecordBackend record SqlBackend, Typeable record, MonadSqlQuery m) + => Key record -> m () +delete a1 = runQueryRep $ Delete a1 + +update + :: (PersistRecordBackend record SqlBackend, Typeable record, MonadSqlQuery m) + => Key record -> [Update record] -> m () +update a1 a2 = runQueryRep $ Update a1 a2 + +updateGet + :: (PersistRecordBackend record SqlBackend, Typeable record, MonadSqlQuery m) + => Key record -> [Update record] -> m record +updateGet a1 a2 = runQueryRep $ UpdateGet a1 a2 + +insertEntity + :: (PersistRecordBackend record SqlBackend, Typeable record, MonadSqlQuery m) + => record -> m (Entity record) +insertEntity a1 = runQueryRep $ InsertEntity a1 + +insertRecord + :: (PersistRecordBackend record SqlBackend, Typeable record, MonadSqlQuery m) + => record -> m record +insertRecord a1 = runQueryRep $ InsertRecord a1 + +getBy + :: (PersistRecordBackend record SqlBackend, Typeable record, MonadSqlQuery m) + => Unique record -> m (Maybe (Entity record)) +getBy a1 = runQueryRep $ GetBy a1 + +getByValue + :: (PersistRecordBackend record SqlBackend, AtLeastOneUniqueKey record, Typeable record, MonadSqlQuery m) + => record -> m (Maybe (Entity record)) +getByValue a1 = runQueryRep $ GetByValue a1 + +checkUnique + :: (PersistRecordBackend record SqlBackend, Typeable record, MonadSqlQuery m) + => record -> m (Maybe (Unique record)) +checkUnique a1 = runQueryRep $ CheckUnique a1 + +deleteBy + :: (PersistRecordBackend record SqlBackend, Typeable record, MonadSqlQuery m) + => Unique record -> m () +deleteBy a1 = runQueryRep $ DeleteBy a1 + +insertUnique + :: (PersistRecordBackend record SqlBackend, Typeable record, MonadSqlQuery m) + => record -> m (Maybe (Key record)) +insertUnique a1 = runQueryRep $ InsertUnique a1 + +upsert + :: (PersistRecordBackend record SqlBackend, OnlyOneUniqueKey record, Typeable record, MonadSqlQuery m) + => record -> [Update record] -> m (Entity record) +upsert a1 a2 = runQueryRep $ Upsert a1 a2 + +upsertBy + :: (PersistRecordBackend record SqlBackend, Typeable record, MonadSqlQuery m) + => Unique record -> record -> [Update record] -> m (Entity record) +upsertBy a1 a2 a3 = runQueryRep $ UpsertBy a1 a2 a3 + +putMany + :: (PersistRecordBackend record SqlBackend, Typeable record, MonadSqlQuery m) + => [record] -> m () +putMany a1 = runQueryRep $ PutMany a1 + +insertBy + :: (PersistRecordBackend record SqlBackend, AtLeastOneUniqueKey record, Typeable record, MonadSqlQuery m) + => record -> m (Either (Entity record) (Key record)) +insertBy a1 = runQueryRep $ InsertBy a1 + +insertUniqueEntity + :: (PersistRecordBackend record SqlBackend, Typeable record, MonadSqlQuery m) + => record -> m (Maybe (Entity record)) +insertUniqueEntity a1 = runQueryRep $ InsertUniqueEntity a1 + +replaceUnique + :: (PersistRecordBackend record SqlBackend, Eq (Unique record), Typeable record, MonadSqlQuery m) + => Key record -> record -> m (Maybe (Unique record)) +replaceUnique a1 a2 = runQueryRep $ ReplaceUnique a1 a2 + +onlyUnique + :: (PersistRecordBackend record SqlBackend, OnlyOneUniqueKey record, Typeable record, MonadSqlQuery m) + => record -> m (Unique record) +onlyUnique a1 = runQueryRep $ OnlyUnique a1 + +selectFirst + :: (PersistRecordBackend record SqlBackend, Typeable record, MonadSqlQuery m) + => [Filter record] -> [SelectOpt record] -> m (Maybe (Entity record)) +selectFirst a1 a2 = runQueryRep $ SelectFirst a1 a2 + +count + :: (PersistRecordBackend record SqlBackend, Typeable record, MonadSqlQuery m) + => [Filter record] -> m Int +count a1 = runQueryRep $ Count a1 + +selectList + :: (PersistRecordBackend record SqlBackend, Typeable record, MonadSqlQuery m) + => [Filter record] -> [SelectOpt record] -> m [Entity record] +selectList a1 a2 = runQueryRep $ SelectList a1 a2 + +selectKeysList + :: (PersistRecordBackend record SqlBackend, Typeable record, MonadSqlQuery m) + => [Filter record] -> [SelectOpt record] -> m [Key record] +selectKeysList a1 a2 = runQueryRep $ SelectKeysList a1 a2 + +updateWhere + :: (PersistRecordBackend record SqlBackend, Typeable record, MonadSqlQuery m) + => [Filter record] -> [Update record] -> m () +updateWhere a1 a2 = runQueryRep $ UpdateWhere a1 a2 + +deleteWhere + :: (PersistRecordBackend record SqlBackend, Typeable record, MonadSqlQuery m) + => [Filter record] -> m () +deleteWhere a1 = runQueryRep $ DeleteWhere a1 + +deleteWhereCount + :: (PersistRecordBackend record SqlBackend, Typeable record, MonadSqlQuery m) + => [Filter record] -> m Int64 +deleteWhereCount a1 = runQueryRep $ DeleteWhereCount a1 + +updateWhereCount + :: (PersistRecordBackend record SqlBackend, Typeable record, MonadSqlQuery m) + => [Filter record] -> [Update record] -> m Int64 +updateWhereCount a1 a2 = runQueryRep $ UpdateWhereCount a1 a2 + +deleteCascade + :: (DeleteCascade record SqlBackend, Typeable record, MonadSqlQuery m) + => Key record -> m () +deleteCascade a1 = runQueryRep $ DeleteCascade a1 + +deleteCascadeWhere + :: (DeleteCascade record SqlBackend, Typeable record, MonadSqlQuery m) + => [Filter record] -> m () +deleteCascadeWhere a1 = runQueryRep $ DeleteCascadeWhere a1 + +parseMigration + :: (HasCallStack, MonadSqlQuery m) + => Migration -> m (Either [Text] CautiousMigration) +parseMigration a1 = runQueryRep $ ParseMigration a1 + +parseMigration' + :: (HasCallStack, MonadSqlQuery m) + => Migration -> m CautiousMigration +parseMigration' a1 = runQueryRep $ ParseMigration' a1 + +printMigration + :: (HasCallStack, MonadSqlQuery m) + => Migration -> m () +printMigration a1 = runQueryRep $ PrintMigration a1 + +showMigration + :: (HasCallStack, MonadSqlQuery m) + => Migration -> m [Text] +showMigration a1 = runQueryRep $ ShowMigration a1 + +getMigration + :: (HasCallStack, MonadSqlQuery m) + => Migration -> m [Sql] +getMigration a1 = runQueryRep $ GetMigration a1 + +runMigration + :: (MonadSqlQuery m) + => Migration -> m () +runMigration a1 = runQueryRep $ RunMigration a1 + +runMigrationQuiet + :: (MonadSqlQuery m) + => Migration -> m [Text] +runMigrationQuiet a1 = runQueryRep $ RunMigrationQuiet a1 + +runMigrationSilent + :: (MonadSqlQuery m) + => Migration -> m [Text] +runMigrationSilent a1 = runQueryRep $ RunMigrationSilent a1 + +runMigrationUnsafe + :: (MonadSqlQuery m) + => Migration -> m () +runMigrationUnsafe a1 = runQueryRep $ RunMigrationUnsafe a1 + +runMigrationUnsafeQuiet + :: (HasCallStack, MonadSqlQuery m) + => Migration -> m [Text] +runMigrationUnsafeQuiet a1 = runQueryRep $ RunMigrationUnsafeQuiet a1 + +getFieldName + :: (PersistRecordBackend record SqlBackend, Typeable record, MonadSqlQuery m) + => EntityField record typ -> m Text +getFieldName a1 = runQueryRep $ GetFieldName a1 + +getTableName + :: (PersistEntity record, Typeable record, MonadSqlQuery m) + => record -> m Text +getTableName a1 = runQueryRep $ GetTableName a1 + +withRawQuery + :: (MonadSqlQuery m) + => Text -> [PersistValue] -> ConduitM [PersistValue] Void IO a -> m a +withRawQuery a1 a2 a3 = runQueryRep $ WithRawQuery a1 a2 a3 + +rawExecute + :: (MonadSqlQuery m) + => Text -> [PersistValue] -> m () +rawExecute a1 a2 = runQueryRep $ RawExecute a1 a2 + +rawExecuteCount + :: (MonadSqlQuery m) + => Text -> [PersistValue] -> m Int64 +rawExecuteCount a1 a2 = runQueryRep $ RawExecuteCount a1 a2 + +rawSql + :: (RawSql a, MonadSqlQuery m) + => Text -> [PersistValue] -> m [a] +rawSql a1 a2 = runQueryRep $ RawSql a1 a2 + +transactionSave + :: (MonadSqlQuery m) + => m () +transactionSave = runQueryRep $ TransactionSave + +transactionSaveWithIsolation + :: (MonadSqlQuery m) + => IsolationLevel -> m () +transactionSaveWithIsolation a1 = runQueryRep $ TransactionSaveWithIsolation a1 + +transactionUndo + :: (MonadSqlQuery m) + => m () +transactionUndo = runQueryRep $ TransactionUndo + +transactionUndoWithIsolation + :: (MonadSqlQuery m) + => IsolationLevel -> m () +transactionUndoWithIsolation a1 = runQueryRep $ TransactionUndoWithIsolation a1 diff --git a/src/Database/Persist/Monad/SqlQueryRep.hs b/src/Database/Persist/Monad/SqlQueryRep.hs index 81da417..d39d4b1 100644 --- a/src/Database/Persist/Monad/SqlQueryRep.hs +++ b/src/Database/Persist/Monad/SqlQueryRep.hs @@ -1,5 +1,7 @@ +{-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE GADTs #-} {-# LANGUAGE LambdaCase #-} +{-# LANGUAGE PatternSynonyms #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeApplications #-} @@ -9,34 +11,37 @@ module Database.Persist.Monad.SqlQueryRep ) where import Control.Monad.IO.Unlift (MonadUnliftIO) +import Data.Conduit (ConduitM) +import Data.Int (Int64) import Data.Map (Map) import Data.Proxy (Proxy(..)) import Data.Text (Text) import Data.Typeable (Typeable, eqT, typeRep, (:~:)(..)) import Data.Void (Void) -import Database.Persist.Sql as Persist +import Database.Persist.Sql as Persist hiding (pattern Update) +import GHC.Stack (HasCallStack) -data SqlQueryRep record a where - {- PersistStoreRead -} +{-# ANN module "HLint: ignore" #-} +data SqlQueryRep record a where Get - :: PersistRecordBackend record SqlBackend + :: (PersistRecordBackend record SqlBackend) => Key record -> SqlQueryRep record (Maybe record) GetMany - :: PersistRecordBackend record SqlBackend + :: (PersistRecordBackend record SqlBackend) => [Key record] -> SqlQueryRep record (Map (Key record) record) GetJust - :: PersistRecordBackend record SqlBackend + :: (PersistRecordBackend record SqlBackend) => Key record -> SqlQueryRep record record GetJustEntity - :: PersistRecordBackend record SqlBackend + :: (PersistRecordBackend record SqlBackend) => Key record -> SqlQueryRep record (Entity record) GetEntity - :: PersistRecordBackend record SqlBackend + :: (PersistRecordBackend record SqlBackend) => Key record -> SqlQueryRep record (Maybe (Entity record)) BelongsTo @@ -47,22 +52,229 @@ data SqlQueryRep record a where :: (PersistEntity record1, PersistRecordBackend record2 SqlBackend) => (record1 -> Key record2) -> record1 -> SqlQueryRep (record1, record2) record2 - {- Other -} - - SelectList - :: PersistRecordBackend record SqlBackend - => [Filter record] -> [SelectOpt record] -> SqlQueryRep record [Entity record] - Insert - :: PersistRecordBackend record SqlBackend + :: (PersistRecordBackend record SqlBackend) => record -> SqlQueryRep record (Key record) Insert_ - :: PersistRecordBackend record SqlBackend + :: (PersistRecordBackend record SqlBackend) => record -> SqlQueryRep record () - RunMigrationsSilent - :: Migration -> SqlQueryRep Void [Text] + InsertMany + :: (PersistRecordBackend record SqlBackend) + => [record] -> SqlQueryRep record [Key record] + + InsertMany_ + :: (PersistRecordBackend record SqlBackend) + => [record] -> SqlQueryRep record () + + InsertEntityMany + :: (PersistRecordBackend record SqlBackend) + => [Entity record] -> SqlQueryRep record () + + InsertKey + :: (PersistRecordBackend record SqlBackend) + => Key record -> record -> SqlQueryRep record () + + Repsert + :: (PersistRecordBackend record SqlBackend) + => Key record -> record -> SqlQueryRep record () + + RepsertMany + :: (PersistRecordBackend record SqlBackend) + => [(Key record, record)] -> SqlQueryRep record () + + Replace + :: (PersistRecordBackend record SqlBackend) + => Key record -> record -> SqlQueryRep record () + + Delete + :: (PersistRecordBackend record SqlBackend) + => Key record -> SqlQueryRep record () + + Update + :: (PersistRecordBackend record SqlBackend) + => Key record -> [Update record] -> SqlQueryRep record () + + UpdateGet + :: (PersistRecordBackend record SqlBackend) + => Key record -> [Update record] -> SqlQueryRep record record + + InsertEntity + :: (PersistRecordBackend record SqlBackend) + => record -> SqlQueryRep record (Entity record) + + InsertRecord + :: (PersistRecordBackend record SqlBackend) + => record -> SqlQueryRep record record + + GetBy + :: (PersistRecordBackend record SqlBackend) + => Unique record -> SqlQueryRep record (Maybe (Entity record)) + + GetByValue + :: (PersistRecordBackend record SqlBackend, AtLeastOneUniqueKey record) + => record -> SqlQueryRep record (Maybe (Entity record)) + + CheckUnique + :: (PersistRecordBackend record SqlBackend) + => record -> SqlQueryRep record (Maybe (Unique record)) + + DeleteBy + :: (PersistRecordBackend record SqlBackend) + => Unique record -> SqlQueryRep record () + + InsertUnique + :: (PersistRecordBackend record SqlBackend) + => record -> SqlQueryRep record (Maybe (Key record)) + + Upsert + :: (PersistRecordBackend record SqlBackend, OnlyOneUniqueKey record) + => record -> [Update record] -> SqlQueryRep record (Entity record) + + UpsertBy + :: (PersistRecordBackend record SqlBackend) + => Unique record -> record -> [Update record] -> SqlQueryRep record (Entity record) + + PutMany + :: (PersistRecordBackend record SqlBackend) + => [record] -> SqlQueryRep record () + + InsertBy + :: (PersistRecordBackend record SqlBackend, AtLeastOneUniqueKey record) + => record -> SqlQueryRep record (Either (Entity record) (Key record)) + + InsertUniqueEntity + :: (PersistRecordBackend record SqlBackend) + => record -> SqlQueryRep record (Maybe (Entity record)) + + ReplaceUnique + :: (PersistRecordBackend record SqlBackend, Eq (Unique record)) + => Key record -> record -> SqlQueryRep record (Maybe (Unique record)) + + OnlyUnique + :: (PersistRecordBackend record SqlBackend, OnlyOneUniqueKey record) + => record -> SqlQueryRep record (Unique record) + + SelectFirst + :: (PersistRecordBackend record SqlBackend) + => [Filter record] -> [SelectOpt record] -> SqlQueryRep record (Maybe (Entity record)) + + Count + :: (PersistRecordBackend record SqlBackend) + => [Filter record] -> SqlQueryRep record Int + + SelectList + :: (PersistRecordBackend record SqlBackend) + => [Filter record] -> [SelectOpt record] -> SqlQueryRep record [Entity record] + + SelectKeysList + :: (PersistRecordBackend record SqlBackend) + => [Filter record] -> [SelectOpt record] -> SqlQueryRep record [Key record] + + UpdateWhere + :: (PersistRecordBackend record SqlBackend) + => [Filter record] -> [Update record] -> SqlQueryRep record () + + DeleteWhere + :: (PersistRecordBackend record SqlBackend) + => [Filter record] -> SqlQueryRep record () + + DeleteWhereCount + :: (PersistRecordBackend record SqlBackend) + => [Filter record] -> SqlQueryRep record Int64 + + UpdateWhereCount + :: (PersistRecordBackend record SqlBackend) + => [Filter record] -> [Update record] -> SqlQueryRep record Int64 + + DeleteCascade + :: (DeleteCascade record SqlBackend) + => Key record -> SqlQueryRep record () + + DeleteCascadeWhere + :: (DeleteCascade record SqlBackend) + => [Filter record] -> SqlQueryRep record () + + ParseMigration + :: (HasCallStack) + => Migration -> SqlQueryRep Void (Either [Text] CautiousMigration) + + ParseMigration' + :: (HasCallStack) + => Migration -> SqlQueryRep Void CautiousMigration + + PrintMigration + :: (HasCallStack) + => Migration -> SqlQueryRep Void () + + ShowMigration + :: (HasCallStack) + => Migration -> SqlQueryRep Void [Text] + + GetMigration + :: (HasCallStack) + => Migration -> SqlQueryRep Void [Sql] + + RunMigration + :: () + => Migration -> SqlQueryRep Void () + + RunMigrationQuiet + :: () + => Migration -> SqlQueryRep Void [Text] + + RunMigrationSilent + :: () + => Migration -> SqlQueryRep Void [Text] + + RunMigrationUnsafe + :: () + => Migration -> SqlQueryRep Void () + + RunMigrationUnsafeQuiet + :: (HasCallStack) + => Migration -> SqlQueryRep Void [Text] + + GetFieldName + :: (PersistRecordBackend record SqlBackend) + => EntityField record typ -> SqlQueryRep record Text + + GetTableName + :: (PersistEntity record) + => record -> SqlQueryRep record Text + + WithRawQuery + :: () + => Text -> [PersistValue] -> ConduitM [PersistValue] Void IO a -> SqlQueryRep Void a + + RawExecute + :: () + => Text -> [PersistValue] -> SqlQueryRep Void () + + RawExecuteCount + :: () + => Text -> [PersistValue] -> SqlQueryRep Void Int64 + + RawSql + :: (RawSql a) + => Text -> [PersistValue] -> SqlQueryRep Void [a] + + TransactionSave + :: () + => SqlQueryRep Void () + + TransactionSaveWithIsolation + :: () + => IsolationLevel -> SqlQueryRep Void () + + TransactionUndo + :: () + => SqlQueryRep Void () + + TransactionUndoWithIsolation + :: () + => IsolationLevel -> SqlQueryRep Void () instance Typeable record => Show (SqlQueryRep record a) where show = \case @@ -73,11 +285,62 @@ instance Typeable record => Show (SqlQueryRep record a) where GetEntity{} -> "GetEntity{..}" ++ record BelongsTo{} -> "BelongsTo{..}" ++ record BelongsToJust{} -> "BelongsToJust{..}" ++ record - - SelectList{} -> "SelectList{..}" ++ record Insert{} -> "Insert{..}" ++ record Insert_{} -> "Insert_{..}" ++ record - RunMigrationsSilent{} -> "RunMigrationsSilent{..}" ++ record + InsertMany{} -> "InsertMany{..}" ++ record + InsertMany_{} -> "InsertMany_{..}" ++ record + InsertEntityMany{} -> "InsertEntityMany{..}" ++ record + InsertKey{} -> "InsertKey{..}" ++ record + Repsert{} -> "Repsert{..}" ++ record + RepsertMany{} -> "RepsertMany{..}" ++ record + Replace{} -> "Replace{..}" ++ record + Delete{} -> "Delete{..}" ++ record + Update{} -> "Update{..}" ++ record + UpdateGet{} -> "UpdateGet{..}" ++ record + InsertEntity{} -> "InsertEntity{..}" ++ record + InsertRecord{} -> "InsertRecord{..}" ++ record + GetBy{} -> "GetBy{..}" ++ record + GetByValue{} -> "GetByValue{..}" ++ record + CheckUnique{} -> "CheckUnique{..}" ++ record + DeleteBy{} -> "DeleteBy{..}" ++ record + InsertUnique{} -> "InsertUnique{..}" ++ record + Upsert{} -> "Upsert{..}" ++ record + UpsertBy{} -> "UpsertBy{..}" ++ record + PutMany{} -> "PutMany{..}" ++ record + InsertBy{} -> "InsertBy{..}" ++ record + InsertUniqueEntity{} -> "InsertUniqueEntity{..}" ++ record + ReplaceUnique{} -> "ReplaceUnique{..}" ++ record + OnlyUnique{} -> "OnlyUnique{..}" ++ record + SelectFirst{} -> "SelectFirst{..}" ++ record + Count{} -> "Count{..}" ++ record + SelectList{} -> "SelectList{..}" ++ record + SelectKeysList{} -> "SelectKeysList{..}" ++ record + UpdateWhere{} -> "UpdateWhere{..}" ++ record + DeleteWhere{} -> "DeleteWhere{..}" ++ record + DeleteWhereCount{} -> "DeleteWhereCount{..}" ++ record + UpdateWhereCount{} -> "UpdateWhereCount{..}" ++ record + DeleteCascade{} -> "DeleteCascade{..}" ++ record + DeleteCascadeWhere{} -> "DeleteCascadeWhere{..}" ++ record + ParseMigration{} -> "ParseMigration{..}" ++ record + ParseMigration'{} -> "ParseMigration'{..}" ++ record + PrintMigration{} -> "PrintMigration{..}" ++ record + ShowMigration{} -> "ShowMigration{..}" ++ record + GetMigration{} -> "GetMigration{..}" ++ record + RunMigration{} -> "RunMigration{..}" ++ record + RunMigrationQuiet{} -> "RunMigrationQuiet{..}" ++ record + RunMigrationSilent{} -> "RunMigrationSilent{..}" ++ record + RunMigrationUnsafe{} -> "RunMigrationUnsafe{..}" ++ record + RunMigrationUnsafeQuiet{} -> "RunMigrationUnsafeQuiet{..}" ++ record + GetFieldName{} -> "GetFieldName{..}" ++ record + GetTableName{} -> "GetTableName{..}" ++ record + WithRawQuery{} -> "WithRawQuery{..}" ++ record + RawExecute{} -> "RawExecute{..}" ++ record + RawExecuteCount{} -> "RawExecuteCount{..}" ++ record + RawSql{} -> "RawSql{..}" ++ record + TransactionSave{} -> "TransactionSave{..}" ++ record + TransactionSaveWithIsolation{} -> "TransactionSaveWithIsolation{..}" ++ record + TransactionUndo{} -> "TransactionUndo{..}" ++ record + TransactionUndoWithIsolation{} -> "TransactionUndoWithIsolation{..}" ++ record where record = case recordTypeRep of Just recordType -> "<" ++ show recordType ++ ">" @@ -88,15 +351,66 @@ instance Typeable record => Show (SqlQueryRep record a) where runSqlQueryRep :: MonadUnliftIO m => SqlQueryRep record a -> Persist.SqlPersistT m a runSqlQueryRep = \case - Get a -> Persist.get a - GetMany a -> Persist.getMany a - GetJust a -> Persist.getJust a - GetJustEntity a -> Persist.getJustEntity a - GetEntity a -> Persist.getEntity a - BelongsTo a b -> Persist.belongsTo a b - BelongsToJust a b -> Persist.belongsToJust a b - - SelectList a b -> Persist.selectList a b - Insert a -> Persist.insert a - Insert_ a -> Persist.insert_ a - RunMigrationsSilent a -> Persist.runMigrationSilent a + Get a1 -> Persist.get a1 + GetMany a1 -> Persist.getMany a1 + GetJust a1 -> Persist.getJust a1 + GetJustEntity a1 -> Persist.getJustEntity a1 + GetEntity a1 -> Persist.getEntity a1 + BelongsTo a1 a2 -> Persist.belongsTo a1 a2 + BelongsToJust a1 a2 -> Persist.belongsToJust a1 a2 + Insert a1 -> Persist.insert a1 + Insert_ a1 -> Persist.insert_ a1 + InsertMany a1 -> Persist.insertMany a1 + InsertMany_ a1 -> Persist.insertMany_ a1 + InsertEntityMany a1 -> Persist.insertEntityMany a1 + InsertKey a1 a2 -> Persist.insertKey a1 a2 + Repsert a1 a2 -> Persist.repsert a1 a2 + RepsertMany a1 -> Persist.repsertMany a1 + Replace a1 a2 -> Persist.replace a1 a2 + Delete a1 -> Persist.delete a1 + Update a1 a2 -> Persist.update a1 a2 + UpdateGet a1 a2 -> Persist.updateGet a1 a2 + InsertEntity a1 -> Persist.insertEntity a1 + InsertRecord a1 -> Persist.insertRecord a1 + GetBy a1 -> Persist.getBy a1 + GetByValue a1 -> Persist.getByValue a1 + CheckUnique a1 -> Persist.checkUnique a1 + DeleteBy a1 -> Persist.deleteBy a1 + InsertUnique a1 -> Persist.insertUnique a1 + Upsert a1 a2 -> Persist.upsert a1 a2 + UpsertBy a1 a2 a3 -> Persist.upsertBy a1 a2 a3 + PutMany a1 -> Persist.putMany a1 + InsertBy a1 -> Persist.insertBy a1 + InsertUniqueEntity a1 -> Persist.insertUniqueEntity a1 + ReplaceUnique a1 a2 -> Persist.replaceUnique a1 a2 + OnlyUnique a1 -> Persist.onlyUnique a1 + SelectFirst a1 a2 -> Persist.selectFirst a1 a2 + Count a1 -> Persist.count a1 + SelectList a1 a2 -> Persist.selectList a1 a2 + SelectKeysList a1 a2 -> Persist.selectKeysList a1 a2 + UpdateWhere a1 a2 -> Persist.updateWhere a1 a2 + DeleteWhere a1 -> Persist.deleteWhere a1 + DeleteWhereCount a1 -> Persist.deleteWhereCount a1 + UpdateWhereCount a1 a2 -> Persist.updateWhereCount a1 a2 + DeleteCascade a1 -> Persist.deleteCascade a1 + DeleteCascadeWhere a1 -> Persist.deleteCascadeWhere a1 + ParseMigration a1 -> Persist.parseMigration a1 + ParseMigration' a1 -> Persist.parseMigration' a1 + PrintMigration a1 -> Persist.printMigration a1 + ShowMigration a1 -> Persist.showMigration a1 + GetMigration a1 -> Persist.getMigration a1 + RunMigration a1 -> Persist.runMigration a1 + RunMigrationQuiet a1 -> Persist.runMigrationQuiet a1 + RunMigrationSilent a1 -> Persist.runMigrationSilent a1 + RunMigrationUnsafe a1 -> Persist.runMigrationUnsafe a1 + RunMigrationUnsafeQuiet a1 -> Persist.runMigrationUnsafeQuiet a1 + GetFieldName a1 -> Persist.getFieldName a1 + GetTableName a1 -> Persist.getTableName a1 + WithRawQuery a1 a2 a3 -> Persist.withRawQuery a1 a2 a3 + RawExecute a1 a2 -> Persist.rawExecute a1 a2 + RawExecuteCount a1 a2 -> Persist.rawExecuteCount a1 a2 + RawSql a1 a2 -> Persist.rawSql a1 a2 + TransactionSave -> Persist.transactionSave + TransactionSaveWithIsolation a1 -> Persist.transactionSaveWithIsolation a1 + TransactionUndo -> Persist.transactionUndo + TransactionUndoWithIsolation a1 -> Persist.transactionUndoWithIsolation a1