Refactor for Database.Esqueleto.Utils
This commit is contained in:
parent
09844a6a78
commit
cc2eb6d475
43
src/Database/Esqueleto/Utils.hs
Normal file
43
src/Database/Esqueleto/Utils.hs
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
module Database.Esqueleto.Utils where
|
||||||
|
|
||||||
|
-- | Convenience for using Esqueleto,
|
||||||
|
-- intended to be imported qualified
|
||||||
|
-- just like Esqueleto
|
||||||
|
|
||||||
|
import ClassyPrelude.Yesod hiding (isInfixOf, (||.))
|
||||||
|
import Data.Foldable as F
|
||||||
|
import Database.Esqueleto as E
|
||||||
|
|
||||||
|
|
||||||
|
-- ezero = E.val (0 :: Int64)
|
||||||
|
|
||||||
|
-- | Often needed with this concrete type
|
||||||
|
true :: E.SqlExpr (E.Value Bool)
|
||||||
|
true = E.val True
|
||||||
|
|
||||||
|
-- | Often needed with this concrete type
|
||||||
|
false :: E.SqlExpr (E.Value Bool)
|
||||||
|
false = E.val False
|
||||||
|
|
||||||
|
-- | Check if the first string is contained in the text derived from the second argument
|
||||||
|
isInfixOf :: (E.Esqueleto query expr backend, E.SqlString s2) =>
|
||||||
|
Text -> expr (E.Value s2) -> expr (E.Value Bool)
|
||||||
|
isInfixOf needle strExpr = E.castString strExpr `E.ilike` (E.%) E.++. E.val needle E.++. (E.%)
|
||||||
|
|
||||||
|
hasInfix :: (E.Esqueleto query expr backend, E.SqlString s2) =>
|
||||||
|
expr (E.Value s2) -> Text -> expr (E.Value Bool)
|
||||||
|
hasInfix = flip isInfixOf
|
||||||
|
|
||||||
|
-- | Given a test and a set of values, check whether anyone succeeds the test
|
||||||
|
-- WARNING: SQL leaves it explicitely unspecified whether || is short curcuited (i.e. lazily evaluated)
|
||||||
|
any :: Foldable f =>
|
||||||
|
(a -> SqlExpr (E.Value Bool)) -> f a -> SqlExpr (E.Value Bool)
|
||||||
|
any test = F.foldr (\needle acc -> acc ||. test needle) false
|
||||||
|
|
||||||
|
-- | Given a test and a set of values, check whether all succeeds the test
|
||||||
|
-- WARNING: SQL leaves it explicitely unspecified whether && is short curcuited (i.e. lazily evaluated)
|
||||||
|
all :: Foldable f =>
|
||||||
|
(a -> SqlExpr (E.Value Bool)) -> f a -> SqlExpr (E.Value Bool)
|
||||||
|
all test = F.foldr (\needle acc -> acc &&. test needle) true
|
||||||
|
|
||||||
|
|
||||||
@ -12,6 +12,7 @@ import qualified Data.Set as Set
|
|||||||
import qualified Data.Map as Map
|
import qualified Data.Map as Map
|
||||||
|
|
||||||
import qualified Database.Esqueleto as E
|
import qualified Database.Esqueleto as E
|
||||||
|
import qualified Database.Esqueleto.Utils as E
|
||||||
|
|
||||||
|
|
||||||
hijackUserForm :: CryptoUUIDUser -> Form ()
|
hijackUserForm :: CryptoUUIDUser -> Form ()
|
||||||
@ -93,16 +94,13 @@ getUsersR = do
|
|||||||
]
|
]
|
||||||
, dbtFilter = Map.fromList -- OverloadedLists does not work with the templates
|
, dbtFilter = Map.fromList -- OverloadedLists does not work with the templates
|
||||||
[ ( "user-search", FilterColumn $ \user criterion ->
|
[ ( "user-search", FilterColumn $ \user criterion ->
|
||||||
-- let searchSql needle = E.castString (user E.^. UserDisplayName) `E.ilike` (E.%) E.++. E.val needle E.++. (E.%) in
|
if Set.null criterion then E.true else -- TODO: why is this condition not needed?
|
||||||
if Set.null criterion then E.val True else -- TODO: why is this condition not needed?
|
-- Set.foldr (\needle acc -> acc E.||. (user E.^. UserDisplayName) `E.hasInfix` needle) eFalse (criterion :: Set.Set Text)
|
||||||
Set.foldr (\needle acc -> acc E.||. (user E.^. UserDisplayName) `eLike` needle) eFalse (criterion :: Set.Set Text)
|
E.any (user E.^. UserDisplayName `E.hasInfix`) criterion
|
||||||
)
|
)
|
||||||
, ( "matriculation", FilterColumn $ \user (criterion :: Set.Set Text) -> if
|
, ( "matriculation", FilterColumn $ \user (criterion :: Set.Set Text) -> if
|
||||||
| Set.null criterion -> eTrue -- TODO: why can this be eFalse and work still?
|
| Set.null criterion -> E.true -- TODO: why can this be eFalse and work still?
|
||||||
| otherwise ->
|
| otherwise -> E.any (user E.^. UserMatrikelnummer `E.hasInfix`) criterion
|
||||||
-- user E.^. UserMatrikelnummer `E.in_` E.justList (E.valList $ Set.toList criterion)
|
|
||||||
Set.foldr (\needle acc -> acc E.||. (user E.^. UserMatrikelnummer) `eLike` needle) eFalse criterion
|
|
||||||
|
|
||||||
)
|
)
|
||||||
, ( "school", FilterColumn $ \user criterion -> if
|
, ( "school", FilterColumn $ \user criterion -> if
|
||||||
| Set.null criterion -> E.val True :: E.SqlExpr (E.Value Bool)
|
| Set.null criterion -> E.val True :: E.SqlExpr (E.Value Bool)
|
||||||
|
|||||||
@ -10,20 +10,6 @@ import qualified Data.Set as Set
|
|||||||
import qualified Database.Esqueleto as E
|
import qualified Database.Esqueleto as E
|
||||||
-- import Database.Persist -- currently not needed here
|
-- import Database.Persist -- currently not needed here
|
||||||
|
|
||||||
-- ezero = E.val (0 :: Int64)
|
|
||||||
|
|
||||||
-- | Often needed with this concrete type
|
|
||||||
eTrue :: E.SqlExpr (E.Value Bool)
|
|
||||||
eTrue = E.val True
|
|
||||||
|
|
||||||
-- | Often needed with this concrete type
|
|
||||||
eFalse :: E.SqlExpr (E.Value Bool)
|
|
||||||
eFalse = E.val False
|
|
||||||
|
|
||||||
eLike :: (E.Esqueleto query expr backend, E.SqlString s2, E.SqlString s1) =>
|
|
||||||
expr (E.Value s2) -> s1 -> expr (E.Value Bool)
|
|
||||||
eLike strExpr needle = E.castString strExpr `E.ilike` (E.%) E.++. E.val needle E.++. (E.%)
|
|
||||||
|
|
||||||
emptyOrIn :: PersistField typ =>
|
emptyOrIn :: PersistField typ =>
|
||||||
E.SqlExpr (E.Value typ) -> Set typ -> E.SqlExpr (E.Value Bool)
|
E.SqlExpr (E.Value typ) -> Set typ -> E.SqlExpr (E.Value Bool)
|
||||||
emptyOrIn criterion testSet
|
emptyOrIn criterion testSet
|
||||||
|
|||||||
75
src/index.md
75
src/index.md
@ -1,40 +1,43 @@
|
|||||||
|
Database,Esqueleto.*
|
||||||
|
: Hilfsdefinitionen, welche Esqueleto anbieten könnte
|
||||||
|
|
||||||
Utils, Utils.*
|
Utils, Utils.*
|
||||||
: Hilfsfunktionionen _unabhängig von Foundation_
|
: Hilfsfunktionionen _unabhängig von Foundation_
|
||||||
|
|
||||||
Utils
|
Utils
|
||||||
: Yesod Hilfsfunktionen und Instanzen, Text-HTML-Widget-Konvertierungen
|
: Yesod Hilfsfunktionen und Instanzen, Text-HTML-Widget-Konvertierungen
|
||||||
(`DisplayAble`), Crud, `NTop`, Utility-Funktionen für `MonadPlus`, `Maybe`,
|
(`DisplayAble`), Crud, `NTop`, Utility-Funktionen für `MonadPlus`, `Maybe`,
|
||||||
`MaybeT`, `Map`, und Attrs-Lists
|
`MaybeT`, `Map`, und Attrs-Lists
|
||||||
|
|
||||||
Utils.TH
|
Utils.TH
|
||||||
: Template Haskell code-generatoren von unabhängigen Hilfsfunktionen (`deriveSimpleWith`)
|
: Template Haskell code-generatoren von unabhängigen Hilfsfunktionen (`deriveSimpleWith`)
|
||||||
|
|
||||||
Utils.DB
|
Utils.DB
|
||||||
: Derived persistent functions (`existsBy`, `getKeyBy404`, ...)
|
: Derived persistent functions (`existsBy`, `getKeyBy404`, ...)
|
||||||
|
|
||||||
Utils.Form
|
Utils.Form
|
||||||
: `renderAForm`, Field-Settings helper, `FormIdentifier`, `Button`-Klasse,
|
: `renderAForm`, Field-Settings helper, `FormIdentifier`, `Button`-Klasse,
|
||||||
unabhängige konkrete Buttons
|
unabhängige konkrete Buttons
|
||||||
|
|
||||||
Utils.PathPiece
|
Utils.PathPiece
|
||||||
: (Template-Haskell)-Hilfsfunktionen für Formulierung von PathPiece-Instanzen
|
: (Template-Haskell)-Hilfsfunktionen für Formulierung von PathPiece-Instanzen
|
||||||
|
|
||||||
Utils.Message
|
Utils.Message
|
||||||
: redefines addMessage, addMessageI, defines MessageClass
|
: redefines addMessage, addMessageI, defines MessageClass
|
||||||
|
|
||||||
Utils.Lens
|
Utils.Lens
|
||||||
: Automatisch erzeugt Linsen für eigene und Yesod-Typen, `Control.Lens`-Export
|
: Automatisch erzeugt Linsen für eigene und Yesod-Typen, `Control.Lens`-Export
|
||||||
|
|
||||||
Utils.DateTime
|
Utils.DateTime
|
||||||
: Template Haskell code-generatoren zum compile-time einbinden von Zeitzone
|
: Template Haskell code-generatoren zum compile-time einbinden von Zeitzone
|
||||||
und `TimeLocale`
|
und `TimeLocale`
|
||||||
|
|
||||||
Handler.Utils, Handler.Utils.*
|
Handler.Utils, Handler.Utils.*
|
||||||
: Hilfsfunktionien, importieren `Import`
|
: Hilfsfunktionien, importieren `Import`
|
||||||
|
|
||||||
Handler.Utils
|
Handler.Utils
|
||||||
: `Handler.Utils.*`, Unsortierte _Foundation-abhängige_ Hilfsfunktionen
|
: `Handler.Utils.*`, Unsortierte _Foundation-abhängige_ Hilfsfunktionen
|
||||||
|
|
||||||
Handler.Utils.DateTime
|
Handler.Utils.DateTime
|
||||||
: Nutzer-spezifisches `DateTime`-Formatieren
|
: Nutzer-spezifisches `DateTime`-Formatieren
|
||||||
|
|
||||||
@ -42,39 +45,39 @@ Handler.Utils.Form
|
|||||||
: Konkrete Buttons, spezielle Felder (inkl. Datei-Upload-Felder),
|
: Konkrete Buttons, spezielle Felder (inkl. Datei-Upload-Felder),
|
||||||
Optionslisten (`optionsPersistCryptoId`), `forced`-Felder (erzwungenes
|
Optionslisten (`optionsPersistCryptoId`), `forced`-Felder (erzwungenes
|
||||||
Ergebnis, deaktiviertes Feld), `multiAction`
|
Ergebnis, deaktiviertes Feld), `multiAction`
|
||||||
|
|
||||||
Handler.Utils.Rating
|
Handler.Utils.Rating
|
||||||
: `Rating` (kodiert eine Rating-Datei), Parsen und PrettyPrinten von
|
: `Rating` (kodiert eine Rating-Datei), Parsen und PrettyPrinten von
|
||||||
Rating-Dateien
|
Rating-Dateien
|
||||||
|
|
||||||
Handler.Utils.Sheet
|
Handler.Utils.Sheet
|
||||||
: `fetchSheet`
|
: `fetchSheet`
|
||||||
|
|
||||||
Handler.Utils.StudyFeatures
|
Handler.Utils.StudyFeatures
|
||||||
: Parsen von LDAP StudyFeatures-Strings
|
: Parsen von LDAP StudyFeatures-Strings
|
||||||
|
|
||||||
Handler.Utils.Submission
|
Handler.Utils.Submission
|
||||||
: `assignSubmissions`, `sinkSubmission` State-Maschinen die (bereits geparste)
|
: `assignSubmissions`, `sinkSubmission` State-Maschinen die (bereits geparste)
|
||||||
ZIP-Archive auseinandernehmen und (in einer Transaction) in die Datenbank
|
ZIP-Archive auseinandernehmen und (in einer Transaction) in die Datenbank
|
||||||
speichern
|
speichern
|
||||||
|
|
||||||
Handler.Utils.Submission.TH
|
Handler.Utils.Submission.TH
|
||||||
: Template Haskell zum parsen und einkompilieren von Dateiname-Blacklist für
|
: Template Haskell zum parsen und einkompilieren von Dateiname-Blacklist für
|
||||||
`sinkSubmission`; Patterns in `config/submission-blacklist`
|
`sinkSubmission`; Patterns in `config/submission-blacklist`
|
||||||
|
|
||||||
Handler.Utils.Table
|
Handler.Utils.Table
|
||||||
: Hilfsfunktion zum direkten Benutzen von Colonnade (kein `dbTable`)
|
: Hilfsfunktion zum direkten Benutzen von Colonnade (kein `dbTable`)
|
||||||
|
|
||||||
Handler.Utils.Table.Pagination
|
Handler.Utils.Table.Pagination
|
||||||
: Here be Dragons
|
: Here be Dragons
|
||||||
|
|
||||||
Paginated database-backed tables with support for sorting, filtering,
|
Paginated database-backed tables with support for sorting, filtering,
|
||||||
numbering, forms, further database-requests within cells
|
numbering, forms, further database-requests within cells
|
||||||
|
|
||||||
Includes helper functions for mangling pagination-, sorting-, and filter-settings
|
Includes helper functions for mangling pagination-, sorting-, and filter-settings
|
||||||
|
|
||||||
Includes helper functions for constructing common types of cells
|
Includes helper functions for constructing common types of cells
|
||||||
|
|
||||||
Handler.Utils.Table.Pagination.Types
|
Handler.Utils.Table.Pagination.Types
|
||||||
: `Sortable`-Headedness for colonnade
|
: `Sortable`-Headedness for colonnade
|
||||||
|
|
||||||
@ -83,17 +86,17 @@ Handler.Utils.Table.Cells
|
|||||||
|
|
||||||
Handler.Utils.Templates
|
Handler.Utils.Templates
|
||||||
: Modals
|
: Modals
|
||||||
|
|
||||||
Handler.Utils.Zip
|
Handler.Utils.Zip
|
||||||
: Conduit-basiertes ZIP Parsen und Erstellen
|
: Conduit-basiertes ZIP Parsen und Erstellen
|
||||||
|
|
||||||
Handler.Common
|
Handler.Common
|
||||||
: Handler aus dem Scaffolding; Implementierungen von Handlern, die _jede
|
: Handler aus dem Scaffolding; Implementierungen von Handlern, die _jede
|
||||||
Website_ irgendwann braucht
|
Website_ irgendwann braucht
|
||||||
|
|
||||||
CryptoID
|
CryptoID
|
||||||
: Definiert CryptoIDs für custom Typen (aus Model)
|
: Definiert CryptoIDs für custom Typen (aus Model)
|
||||||
|
|
||||||
Model.Migration
|
Model.Migration
|
||||||
: Manuelle Datenbank-Migration
|
: Manuelle Datenbank-Migration
|
||||||
|
|
||||||
@ -103,43 +106,43 @@ Model.Rating
|
|||||||
Jobs
|
Jobs
|
||||||
: `handleJobs` worker thread handling background jobs
|
: `handleJobs` worker thread handling background jobs
|
||||||
`JobQueueException`
|
`JobQueueException`
|
||||||
|
|
||||||
Jobs.Types
|
Jobs.Types
|
||||||
: `Job`, `Notification`, `JobCtl` Types of Jobs
|
: `Job`, `Notification`, `JobCtl` Types of Jobs
|
||||||
|
|
||||||
Cron.Types
|
Cron.Types
|
||||||
: Datentypen zur Spezifikation von Intervallen zu denen Jobs ausgeführt werden
|
: Datentypen zur Spezifikation von Intervallen zu denen Jobs ausgeführt werden
|
||||||
können:
|
können:
|
||||||
|
|
||||||
`Cron`, `CronMatch`, `CronAbsolute`, `CronRepeat`, `Crontab`
|
`Cron`, `CronMatch`, `CronAbsolute`, `CronRepeat`, `Crontab`
|
||||||
|
|
||||||
Cron
|
Cron
|
||||||
: Seiteneffektfreie Berechnungen auf Typen aus `Cron.Types`: `nextCronMatch`
|
: Seiteneffektfreie Berechnungen auf Typen aus `Cron.Types`: `nextCronMatch`
|
||||||
|
|
||||||
Jobs.Queue
|
Jobs.Queue
|
||||||
: Funktionen zum _anstoßen_ von Jobs und zur Kommunikation mit den
|
: Funktionen zum _anstoßen_ von Jobs und zur Kommunikation mit den
|
||||||
Worker-Threads
|
Worker-Threads
|
||||||
|
|
||||||
`writeJobCtl` schickt Nachricht an einen pseudo-Zufälligen worker-thread der
|
`writeJobCtl` schickt Nachricht an einen pseudo-Zufälligen worker-thread der
|
||||||
lokalen Instanz
|
lokalen Instanz
|
||||||
|
|
||||||
`queueJob` und `queueJob'` schreiben neue Jobs in die Instanz-übergreifende
|
`queueJob` und `queueJob'` schreiben neue Jobs in die Instanz-übergreifende
|
||||||
Job-Queue, `queueJob'` stößt außerdem einen lokalen worker-thread an sich
|
Job-Queue, `queueJob'` stößt außerdem einen lokalen worker-thread an sich
|
||||||
des Jobs anzunehmen
|
des Jobs anzunehmen
|
||||||
|
|
||||||
`runDBJobs` ersetzt `runDB` und erlaubt `queueDBJob` zu
|
`runDBJobs` ersetzt `runDB` und erlaubt `queueDBJob` zu
|
||||||
benutzen. `queueDBJob` schreibt einen Job in die Queue; am Ende stößt
|
benutzen. `queueDBJob` schreibt einen Job in die Queue; am Ende stößt
|
||||||
`runDBJobs` lokale worker-threads für alle mit `queueDBJobs` eingetragenen
|
`runDBJobs` lokale worker-threads für alle mit `queueDBJobs` eingetragenen
|
||||||
Jobs an.
|
Jobs an.
|
||||||
|
|
||||||
Jobs.TH
|
Jobs.TH
|
||||||
: Templatehaskell für den dispatch mechanismus für `Jobs`
|
: Templatehaskell für den dispatch mechanismus für `Jobs`
|
||||||
|
|
||||||
Jobs.Crontab
|
Jobs.Crontab
|
||||||
: Generiert `Crontab JobCtl` aus der Datenbank (sammelt alle in den Daten aus
|
: Generiert `Crontab JobCtl` aus der Datenbank (sammelt alle in den Daten aus
|
||||||
der Datenbank impliziten Jobs (notifications zu bestimmten zeiten,
|
der Datenbank impliziten Jobs (notifications zu bestimmten zeiten,
|
||||||
aufräumaktionen, ...) ein)
|
aufräumaktionen, ...) ein)
|
||||||
|
|
||||||
Jobs.Handler.**
|
Jobs.Handler.**
|
||||||
: Via `Jobs.TH` delegiert `Jobs` das Interpretieren und Ausführen eines Werts
|
: Via `Jobs.TH` delegiert `Jobs` das Interpretieren und Ausführen eines Werts
|
||||||
aus `Jobs.Types` an einen dieser Handler
|
aus `Jobs.Types` an einen dieser Handler
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user