Commit 8d66d21e authored by Alfredo Di Napoli's avatar Alfredo Di Napoli

WIP: Port DB operations to transactional API

parent c0f94390
...@@ -295,6 +295,7 @@ library ...@@ -295,6 +295,7 @@ library
Gargantext.Database.Admin.Types.Hyperdata.Document Gargantext.Database.Admin.Types.Hyperdata.Document
Gargantext.Database.Admin.Types.Hyperdata.Folder Gargantext.Database.Admin.Types.Hyperdata.Folder
Gargantext.Database.Admin.Types.Node Gargantext.Database.Admin.Types.Node
Gargantext.Database.Class
Gargantext.Database.Prelude Gargantext.Database.Prelude
Gargantext.Database.Query.Facet Gargantext.Database.Query.Facet
Gargantext.Database.Query.Table.Ngrams Gargantext.Database.Query.Table.Ngrams
......
...@@ -37,6 +37,7 @@ import Gargantext.Database.Admin.Types.Hyperdata.Document ( HyperdataDocument(_h ...@@ -37,6 +37,7 @@ import Gargantext.Database.Admin.Types.Hyperdata.Document ( HyperdataDocument(_h
import Gargantext.Database.Query.Table.Node(defaultList, getNodeWith) import Gargantext.Database.Query.Table.Node(defaultList, getNodeWith)
import Gargantext.Database.Query.Table.NodeContext (selectDocs) import Gargantext.Database.Query.Table.NodeContext (selectDocs)
import Gargantext.Database.Schema.Node ( node_hyperdata ) import Gargantext.Database.Schema.Node ( node_hyperdata )
import Gargantext.Database.Prelude
import Gargantext.Prelude hiding (to) import Gargantext.Prelude hiding (to)
type MinSizeBranch = Int type MinSizeBranch = Int
...@@ -44,7 +45,7 @@ type MinSizeBranch = Int ...@@ -44,7 +45,7 @@ type MinSizeBranch = Int
flowPhylo :: (HasNodeStory env err m, HasDBid NodeType) flowPhylo :: (HasNodeStory env err m, HasDBid NodeType)
=> CorpusId => CorpusId
-> m Phylo -> m Phylo
flowPhylo cId = do flowPhylo cId = runDBQuery $ do
corpus_node <- getNodeWith cId (Proxy @HyperdataCorpus) corpus_node <- getNodeWith cId (Proxy @HyperdataCorpus)
let lang = withDefaultLanguage $ view (node_hyperdata . to _hc_lang) corpus_node let lang = withDefaultLanguage $ view (node_hyperdata . to _hc_lang) corpus_node
......
...@@ -32,7 +32,7 @@ import Gargantext.Core.Text.Ngrams (NgramsType(..)) ...@@ -32,7 +32,7 @@ import Gargantext.Core.Text.Ngrams (NgramsType(..))
import Gargantext.Data.HashMap.Strict.Utils as HM ( unionsWith ) import Gargantext.Data.HashMap.Strict.Utils as HM ( unionsWith )
import Gargantext.Database.Admin.Types.Hyperdata.Document import Gargantext.Database.Admin.Types.Hyperdata.Document
import Gargantext.Database.Admin.Types.Node (ListId, CorpusId, NodeId(..), ContextId (..), MasterCorpusId, NodeType(NodeDocument), UserCorpusId, DocId) import Gargantext.Database.Admin.Types.Node (ListId, CorpusId, NodeId(..), ContextId (..), MasterCorpusId, NodeType(NodeDocument), UserCorpusId, DocId)
import Gargantext.Database.Prelude (DBCmd, runPGSQuery) import Gargantext.Database.Prelude
import Gargantext.Database.Schema.Ngrams () -- toDBid instance import Gargantext.Database.Schema.Ngrams () -- toDBid instance
import Gargantext.Prelude import Gargantext.Prelude
...@@ -60,7 +60,7 @@ countContextsByNgramsWith f m = (total, m') ...@@ -60,7 +60,7 @@ countContextsByNgramsWith f m = (total, m')
getContextsByNgramsUser :: HasDBid NodeType getContextsByNgramsUser :: HasDBid NodeType
=> CorpusId => CorpusId
-> NgramsType -> NgramsType
-> DBCmd err (HashMap NgramsTerm (Set ContextId)) -> DBQuery err x (HashMap NgramsTerm (Set ContextId))
getContextsByNgramsUser cId nt = getContextsByNgramsUser cId nt =
HM.fromListWith (<>) <$> map (\(n,t) -> (NgramsTerm t, Set.singleton n)) HM.fromListWith (<>) <$> map (\(n,t) -> (NgramsTerm t, Set.singleton n))
<$> selectNgramsByContextUser cId nt <$> selectNgramsByContextUser cId nt
...@@ -69,9 +69,9 @@ getContextsByNgramsUser cId nt = ...@@ -69,9 +69,9 @@ getContextsByNgramsUser cId nt =
selectNgramsByContextUser :: HasDBid NodeType selectNgramsByContextUser :: HasDBid NodeType
=> CorpusId => CorpusId
-> NgramsType -> NgramsType
-> DBCmd err [(ContextId, Text)] -> DBQuery err x [(ContextId, Text)]
selectNgramsByContextUser cId' nt' = selectNgramsByContextUser cId' nt' =
runPGSQuery queryNgramsByContextUser mkPGQuery queryNgramsByContextUser
( cId' ( cId'
, toDBid NodeDocument , toDBid NodeDocument
, toDBid nt' , toDBid nt'
...@@ -95,16 +95,16 @@ getContextsByNgramsUser cId nt = ...@@ -95,16 +95,16 @@ getContextsByNgramsUser cId nt =
getTreeInstitutesUser :: HasDBid NodeType getTreeInstitutesUser :: HasDBid NodeType
=> CorpusId => CorpusId
-> NgramsType -> NgramsType
-> DBCmd err (HashMap Text [Text]) -> DBQuery err x (HashMap Text [Text])
getTreeInstitutesUser cId nt = getTreeInstitutesUser cId nt =
HM.unionsWith (++) . map (\(_, hd) -> HM.fromList $ Map.toList $ fromMaybe Map.empty (_hd_institutes_tree hd)) <$> selectHyperDataByContextUser cId nt HM.unionsWith (++) . map (\(_, hd) -> HM.fromList $ Map.toList $ fromMaybe Map.empty (_hd_institutes_tree hd)) <$> selectHyperDataByContextUser cId nt
selectHyperDataByContextUser :: HasDBid NodeType selectHyperDataByContextUser :: HasDBid NodeType
=> CorpusId => CorpusId
-> NgramsType -> NgramsType
-> DBCmd err [(ContextId, HyperdataDocument)] -> DBQuery err x [(ContextId, HyperdataDocument)]
selectHyperDataByContextUser cId' nt' = selectHyperDataByContextUser cId' nt' =
runPGSQuery queryHyperDataByContextUser mkPGQuery queryHyperDataByContextUser
( cId' ( cId'
, toDBid nt' , toDBid nt'
) )
...@@ -127,7 +127,7 @@ getOccByNgramsOnlyFast_withSample :: HasDBid NodeType ...@@ -127,7 +127,7 @@ getOccByNgramsOnlyFast_withSample :: HasDBid NodeType
-> Int -> Int
-> NgramsType -> NgramsType
-> [NgramsTerm] -> [NgramsTerm]
-> DBCmd err (HashMap NgramsTerm Int) -> DBQuery err x (HashMap NgramsTerm Int)
getOccByNgramsOnlyFast_withSample cId int nt ngs = getOccByNgramsOnlyFast_withSample cId int nt ngs =
HM.fromListWith (+) <$> selectNgramsOccurrencesOnlyByContextUser_withSample cId int nt ngs HM.fromListWith (+) <$> selectNgramsOccurrencesOnlyByContextUser_withSample cId int nt ngs
...@@ -135,7 +135,7 @@ getOccByNgramsOnlyFast_withSample cId int nt ngs = ...@@ -135,7 +135,7 @@ getOccByNgramsOnlyFast_withSample cId int nt ngs =
getOccByNgramsOnlyFast :: CorpusId getOccByNgramsOnlyFast :: CorpusId
-> ListId -> ListId
-> NgramsType -> NgramsType
-> DBCmd err (HashMap NgramsTerm [ContextId]) -> DBQuery err x (HashMap NgramsTerm [ContextId])
getOccByNgramsOnlyFast cId lId nt = do getOccByNgramsOnlyFast cId lId nt = do
--HM.fromList <$> map (\(t,n) -> (NgramsTerm t, round n)) <$> run cId lId nt --HM.fromList <$> map (\(t,n) -> (NgramsTerm t, round n)) <$> run cId lId nt
HM.fromList <$> map (\(t, ns) -> (NgramsTerm t, UnsafeMkContextId <$> DPST.fromPGArray ns)) <$> run cId lId nt HM.fromList <$> map (\(t, ns) -> (NgramsTerm t, UnsafeMkContextId <$> DPST.fromPGArray ns)) <$> run cId lId nt
...@@ -144,8 +144,8 @@ getOccByNgramsOnlyFast cId lId nt = do ...@@ -144,8 +144,8 @@ getOccByNgramsOnlyFast cId lId nt = do
run :: CorpusId run :: CorpusId
-> ListId -> ListId
-> NgramsType -> NgramsType
-> DBCmd err [(Text, DPST.PGArray Int)] -> DBQuery err x [(Text, DPST.PGArray Int)]
run cId' lId' nt' = runPGSQuery query run cId' lId' nt' = mkPGQuery query
( cId' ( cId'
, lId' , lId'
, toDBid nt' , toDBid nt'
...@@ -208,10 +208,10 @@ selectNgramsOccurrencesOnlyByContextUser_withSample :: HasDBid NodeType ...@@ -208,10 +208,10 @@ selectNgramsOccurrencesOnlyByContextUser_withSample :: HasDBid NodeType
-> Int -> Int
-> NgramsType -> NgramsType
-> [NgramsTerm] -> [NgramsTerm]
-> DBCmd err [(NgramsTerm, Int)] -> DBQuery err x [(NgramsTerm, Int)]
selectNgramsOccurrencesOnlyByContextUser_withSample cId int nt tms = selectNgramsOccurrencesOnlyByContextUser_withSample cId int nt tms =
fmap (first NgramsTerm) <$> fmap (first NgramsTerm) <$>
runPGSQuery queryNgramsOccurrencesOnlyByContextUser_withSample mkPGQuery queryNgramsOccurrencesOnlyByContextUser_withSample
( int ( int
, toDBid NodeDocument , toDBid NodeDocument
, cId , cId
...@@ -269,10 +269,10 @@ selectNgramsOccurrencesOnlyByContextUser_withSample' :: HasDBid NodeType ...@@ -269,10 +269,10 @@ selectNgramsOccurrencesOnlyByContextUser_withSample' :: HasDBid NodeType
=> CorpusId => CorpusId
-> Int -> Int
-> NgramsType -> NgramsType
-> DBCmd err [(NgramsTerm, Int)] -> DBQuery err x [(NgramsTerm, Int)]
selectNgramsOccurrencesOnlyByContextUser_withSample' cId int nt = selectNgramsOccurrencesOnlyByContextUser_withSample' cId int nt =
fmap (first NgramsTerm) <$> fmap (first NgramsTerm) <$>
runPGSQuery queryNgramsOccurrencesOnlyByContextUser_withSample mkPGQuery queryNgramsOccurrencesOnlyByContextUser_withSample
( int ( int
, toDBid NodeDocument , toDBid NodeDocument
, cId , cId
...@@ -303,7 +303,7 @@ getContextsByNgramsOnlyUser :: HasDBid NodeType ...@@ -303,7 +303,7 @@ getContextsByNgramsOnlyUser :: HasDBid NodeType
-> [ListId] -> [ListId]
-> NgramsType -> NgramsType
-> [NgramsTerm] -> [NgramsTerm]
-> DBCmd err (HashMap NgramsTerm (Set ContextId)) -> DBQuery err x (HashMap NgramsTerm (Set ContextId))
getContextsByNgramsOnlyUser cId ls nt ngs = getContextsByNgramsOnlyUser cId ls nt ngs =
HM.unionsWith (<>) HM.unionsWith (<>)
. map (HM.fromListWith (<>) . map (HM.fromListWith (<>)
...@@ -316,7 +316,7 @@ getNgramsByContextOnlyUser :: HasDBid NodeType ...@@ -316,7 +316,7 @@ getNgramsByContextOnlyUser :: HasDBid NodeType
-> [ListId] -> [ListId]
-> NgramsType -> NgramsType
-> [NgramsTerm] -> [NgramsTerm]
-> DBCmd err (Map ContextId (Set NgramsTerm)) -> DBQuery err x (Map ContextId (Set NgramsTerm))
getNgramsByContextOnlyUser cId ls nt ngs = getNgramsByContextOnlyUser cId ls nt ngs =
Map.unionsWith (<>) Map.unionsWith (<>)
. map ( Map.fromListWith (<>) . map ( Map.fromListWith (<>)
...@@ -332,10 +332,10 @@ selectNgramsOnlyByContextUser :: HasDBid NodeType ...@@ -332,10 +332,10 @@ selectNgramsOnlyByContextUser :: HasDBid NodeType
-> [ListId] -> [ListId]
-> NgramsType -> NgramsType
-> [NgramsTerm] -> [NgramsTerm]
-> DBCmd err [(NgramsTerm, ContextId)] -> DBQuery err x [(NgramsTerm, ContextId)]
selectNgramsOnlyByContextUser cId ls nt tms = selectNgramsOnlyByContextUser cId ls nt tms =
fmap (first NgramsTerm) <$> fmap (first NgramsTerm) <$>
runPGSQuery queryNgramsOnlyByContextUser mkPGQuery queryNgramsOnlyByContextUser
( Values fields ((DPS.Only . unNgramsTerm) <$> tms) ( Values fields ((DPS.Only . unNgramsTerm) <$> tms)
, Values [QualifiedIdentifier Nothing "int4"] , Values [QualifiedIdentifier Nothing "int4"]
(DPS.Only <$> map DPS.toField ls) (DPS.Only <$> map DPS.toField ls)
...@@ -367,7 +367,7 @@ getNgramsByDocOnlyUser :: DocId ...@@ -367,7 +367,7 @@ getNgramsByDocOnlyUser :: DocId
-> [ListId] -> [ListId]
-> NgramsType -> NgramsType
-> [NgramsTerm] -> [NgramsTerm]
-> DBCmd err (HashMap NgramsTerm (Set NodeId)) -> DBQuery err x (HashMap NgramsTerm (Set NodeId))
getNgramsByDocOnlyUser cId ls nt ngs = getNgramsByDocOnlyUser cId ls nt ngs =
HM.unionsWith (<>) HM.unionsWith (<>)
. map (HM.fromListWith (<>) . map (second Set.singleton)) . map (HM.fromListWith (<>) . map (second Set.singleton))
...@@ -378,10 +378,10 @@ selectNgramsOnlyByDocUser :: DocId ...@@ -378,10 +378,10 @@ selectNgramsOnlyByDocUser :: DocId
-> [ListId] -> [ListId]
-> NgramsType -> NgramsType
-> [NgramsTerm] -> [NgramsTerm]
-> DBCmd err [(NgramsTerm, NodeId)] -> DBQuery err x [(NgramsTerm, NodeId)]
selectNgramsOnlyByDocUser dId ls nt tms = selectNgramsOnlyByDocUser dId ls nt tms =
fmap (first NgramsTerm) <$> fmap (first NgramsTerm) <$>
runPGSQuery queryNgramsOnlyByDocUser mkPGQuery queryNgramsOnlyByDocUser
( Values fields ((DPS.Only . unNgramsTerm) <$> tms) ( Values fields ((DPS.Only . unNgramsTerm) <$> tms)
, Values [QualifiedIdentifier Nothing "int4"] , Values [QualifiedIdentifier Nothing "int4"]
(DPS.Only <$> (map DPS.toField ls)) (DPS.Only <$> (map DPS.toField ls))
...@@ -410,7 +410,7 @@ queryNgramsOnlyByDocUser = [sql| ...@@ -410,7 +410,7 @@ queryNgramsOnlyByDocUser = [sql|
getContextsByNgramsMaster :: HasDBid NodeType getContextsByNgramsMaster :: HasDBid NodeType
=> UserCorpusId => UserCorpusId
-> MasterCorpusId -> MasterCorpusId
-> DBCmd err (HashMap Text (Set NodeId)) -> DBQuery err x (HashMap Text (Set NodeId))
getContextsByNgramsMaster ucId mcId = unionsWith (<>) getContextsByNgramsMaster ucId mcId = unionsWith (<>)
. map (HM.fromListWith (<>) . map (\(n,t) -> (t, Set.singleton n))) . map (HM.fromListWith (<>) . map (\(n,t) -> (t, Set.singleton n)))
-- . takeWhile (not . List.null) -- . takeWhile (not . List.null)
...@@ -422,8 +422,8 @@ selectNgramsByContextMaster :: HasDBid NodeType ...@@ -422,8 +422,8 @@ selectNgramsByContextMaster :: HasDBid NodeType
-> UserCorpusId -> UserCorpusId
-> MasterCorpusId -> MasterCorpusId
-> Int -> Int
-> DBCmd err [(NodeId, Text)] -> DBQuery err x [(NodeId, Text)]
selectNgramsByContextMaster n ucId mcId p = runPGSQuery selectNgramsByContextMaster n ucId mcId p = mkPGQuery
queryNgramsByContextMaster' queryNgramsByContextMaster'
( ucId ( ucId
, toDBid NgramsTerms , toDBid NgramsTerms
...@@ -438,7 +438,7 @@ selectNgramsByContextMaster n ucId mcId p = runPGSQuery ...@@ -438,7 +438,7 @@ selectNgramsByContextMaster n ucId mcId p = runPGSQuery
) )
-- | TODO fix context_node_ngrams relation -- | TODO fix context_node_ngrams relation
queryNgramsByContextMaster' :: DPS.Query queryNgramsByContextMaster' :: DPST.Query
queryNgramsByContextMaster' = [sql| queryNgramsByContextMaster' = [sql|
WITH contextsByNgramsUser AS ( WITH contextsByNgramsUser AS (
......
...@@ -21,7 +21,7 @@ import Gargantext.Core.Text.Metrics.TFICF ...@@ -21,7 +21,7 @@ import Gargantext.Core.Text.Metrics.TFICF
import Gargantext.Core.Text.Ngrams (NgramsType(..)) import Gargantext.Core.Text.Ngrams (NgramsType(..))
import Gargantext.Database.Action.Metrics.NgramsByContext (getContextsByNgramsUser, {-getOccByNgramsOnlyFast,-} getOccByNgramsOnlyFast_withSample) import Gargantext.Database.Action.Metrics.NgramsByContext (getContextsByNgramsUser, {-getOccByNgramsOnlyFast,-} getOccByNgramsOnlyFast_withSample)
import Gargantext.Database.Admin.Types.Node -- (ListId, CorpusId, NodeId) import Gargantext.Database.Admin.Types.Node -- (ListId, CorpusId, NodeId)
import Gargantext.Database.Prelude (DBCmd) import Gargantext.Database.Prelude
import Gargantext.Database.Query.Table.NodeContext (selectCountDocs) import Gargantext.Database.Query.Table.NodeContext (selectCountDocs)
import Gargantext.Prelude import Gargantext.Prelude
...@@ -56,7 +56,7 @@ getTficf_withSample :: HasDBid NodeType ...@@ -56,7 +56,7 @@ getTficf_withSample :: HasDBid NodeType
=> UserCorpusId => UserCorpusId
-> MasterCorpusId -> MasterCorpusId
-> NgramsType -> NgramsType
-> DBCmd err (HashMap NgramsTerm Double) -> DBQuery err x (HashMap NgramsTerm Double)
getTficf_withSample cId mId nt = do getTficf_withSample cId mId nt = do
mapTextDoubleLocal <- HM.filter (> 1) mapTextDoubleLocal <- HM.filter (> 1)
<$> HM.map (fromIntegral . Set.size) <$> HM.map (fromIntegral . Set.size)
......
...@@ -21,12 +21,12 @@ import Gargantext.Core ...@@ -21,12 +21,12 @@ import Gargantext.Core
-- import Gargantext.Core.Types.Main (ListType(CandidateTerm)) -- import Gargantext.Core.Types.Main (ListType(CandidateTerm))
import Gargantext.Database.Admin.Types.Node -- (ListId, CorpusId, NodeId) import Gargantext.Database.Admin.Types.Node -- (ListId, CorpusId, NodeId)
-- (ListId, CorpusId, NodeId) -- (ListId, CorpusId, NodeId)
import Gargantext.Database.Prelude (execPGSQuery, DBCmd) import Gargantext.Database.Prelude
import Gargantext.Prelude import Gargantext.Prelude
import qualified Database.PostgreSQL.Simple as DPS import qualified Database.PostgreSQL.Simple as DPS
triggerCountInsert :: HasDBid NodeType => DBCmd err Int64 triggerCountInsert :: HasDBid NodeType => DBUpdate err Int64
triggerCountInsert = execPGSQuery query (toDBid NodeDocument, toDBid NodeList) triggerCountInsert = mkPGUpdate query (toDBid NodeDocument, toDBid NodeList)
where where
query :: DPS.Query query :: DPS.Query
query = [sql| query = [sql|
...@@ -61,11 +61,11 @@ triggerCountInsert = execPGSQuery query (toDBid NodeDocument, toDBid NodeList) ...@@ -61,11 +61,11 @@ triggerCountInsert = execPGSQuery query (toDBid NodeDocument, toDBid NodeList)
EXECUTE PROCEDURE set_ngrams_global_count(); EXECUTE PROCEDURE set_ngrams_global_count();
|] |]
triggerCountInsert2 :: HasDBid NodeType => DBCmd err Int64 triggerCountInsert2 :: HasDBid NodeType => DBUpdate err Int64
triggerCountInsert2 = execPGSQuery query ( toDBid NodeCorpus triggerCountInsert2 = mkPGUpdate query ( toDBid NodeCorpus
, toDBid NodeDocument , toDBid NodeDocument
, toDBid NodeList , toDBid NodeList
) )
where where
query :: DPS.Query query :: DPS.Query
query = [sql| query = [sql|
......
...@@ -20,15 +20,15 @@ import Database.PostgreSQL.Simple qualified as DPS ...@@ -20,15 +20,15 @@ import Database.PostgreSQL.Simple qualified as DPS
import Database.PostgreSQL.Simple.SqlQQ (sql) import Database.PostgreSQL.Simple.SqlQQ (sql)
import Gargantext.Core (HasDBid(..)) import Gargantext.Core (HasDBid(..))
import Gargantext.Database.Admin.Types.Node -- (ListId, CorpusId, NodeId) import Gargantext.Database.Admin.Types.Node -- (ListId, CorpusId, NodeId)
import Gargantext.Database.Prelude (execPGSQuery, DBCmd) import Gargantext.Database.Prelude
import Gargantext.Prelude import Gargantext.Prelude
triggerSearchUpdate :: HasDBid NodeType => DBCmd err Int64 triggerSearchUpdate :: HasDBid NodeType => DBUpdate err Int64
triggerSearchUpdate = execPGSQuery query ( toDBid NodeDocument triggerSearchUpdate = mkPGUpdate query ( toDBid NodeDocument
, toDBid NodeDocument , toDBid NodeDocument
, toDBid NodeContact , toDBid NodeContact
) )
where where
query :: DPS.Query query :: DPS.Query
query = [sql| query = [sql|
...@@ -68,16 +68,16 @@ triggerSearchUpdate = execPGSQuery query ( toDBid NodeDocument ...@@ -68,16 +68,16 @@ triggerSearchUpdate = execPGSQuery query ( toDBid NodeDocument
type Secret = Text type Secret = Text
triggerUpdateHash :: HasDBid NodeType => Secret -> DBCmd err Int64 triggerUpdateHash :: HasDBid NodeType => Secret -> DBUpdate err Int64
triggerUpdateHash secret = execPGSQuery query ( toDBid NodeDocument triggerUpdateHash secret = mkPGUpdate query ( toDBid NodeDocument
, toDBid NodeContact , toDBid NodeContact
, secret , secret
, secret , secret
, toDBid NodeDocument , toDBid NodeDocument
, toDBid NodeContact , toDBid NodeContact
, secret , secret
, secret , secret
) )
where where
query :: DPS.Query query :: DPS.Query
query = [sql| query = [sql|
......
...@@ -20,16 +20,16 @@ import Gargantext.Database.Admin.Trigger.ContextNodeNgrams (triggerCountInsert, ...@@ -20,16 +20,16 @@ import Gargantext.Database.Admin.Trigger.ContextNodeNgrams (triggerCountInsert,
import Gargantext.Database.Admin.Trigger.Contexts (triggerSearchUpdate, triggerUpdateHash) import Gargantext.Database.Admin.Trigger.Contexts (triggerSearchUpdate, triggerUpdateHash)
import Gargantext.Database.Admin.Trigger.NodesContexts ({-triggerDeleteCount,-} triggerInsertCount, triggerUpdateAdd, triggerUpdateDel, MasterListId) -- , triggerCoocInsert) import Gargantext.Database.Admin.Trigger.NodesContexts ({-triggerDeleteCount,-} triggerInsertCount, triggerUpdateAdd, triggerUpdateDel, MasterListId) -- , triggerCoocInsert)
-- , triggerCoocInsert) -- , triggerCoocInsert)
import Gargantext.Database.Prelude (DBCmd) import Gargantext.Database.Prelude
import Gargantext.Prelude import Gargantext.Prelude
------------------------------------------------------------------------ ------------------------------------------------------------------------
initFirstTriggers :: Text -> DBCmd err [Int64] initFirstTriggers :: Text -> DBUpdate err [Int64]
initFirstTriggers secret = do initFirstTriggers secret = do
t0 <- triggerUpdateHash secret t0 <- triggerUpdateHash secret
pure [t0] pure [t0]
initLastTriggers :: MasterListId -> DBCmd err [Int64] initLastTriggers :: MasterListId -> DBUpdate err [Int64]
initLastTriggers lId = do initLastTriggers lId = do
t0 <- triggerSearchUpdate t0 <- triggerSearchUpdate
t1 <- triggerCountInsert t1 <- triggerCountInsert
......
...@@ -21,14 +21,14 @@ import Database.PostgreSQL.Simple.SqlQQ (sql) ...@@ -21,14 +21,14 @@ import Database.PostgreSQL.Simple.SqlQQ (sql)
import Gargantext.Core import Gargantext.Core
import Gargantext.Database.Admin.Config () import Gargantext.Database.Admin.Config ()
import Gargantext.Database.Admin.Types.Node -- (ListId, CorpusId, NodeId) import Gargantext.Database.Admin.Types.Node -- (ListId, CorpusId, NodeId)
import Gargantext.Database.Prelude (execPGSQuery, DBCmd) import Gargantext.Database.Prelude
import Gargantext.Prelude import Gargantext.Prelude
import qualified Database.PostgreSQL.Simple as DPS import qualified Database.PostgreSQL.Simple as DPS
type MasterListId = ListId type MasterListId = ListId
triggerInsertCount :: MasterListId -> DBCmd err Int64 triggerInsertCount :: MasterListId -> DBUpdate err Int64
triggerInsertCount lId = execPGSQuery query (lId, toDBid NodeList) triggerInsertCount lId = mkPGUpdate query (lId, toDBid NodeList)
where where
query :: DPS.Query query :: DPS.Query
query = [sql| query = [sql|
...@@ -63,8 +63,8 @@ triggerInsertCount lId = execPGSQuery query (lId, toDBid NodeList) ...@@ -63,8 +63,8 @@ triggerInsertCount lId = execPGSQuery query (lId, toDBid NodeList)
|] |]
triggerUpdateAdd :: MasterListId -> DBCmd err Int64 triggerUpdateAdd :: MasterListId -> DBUpdate err Int64
triggerUpdateAdd lId = execPGSQuery query (lId, toDBid NodeList) triggerUpdateAdd lId = mkPGUpdate query (lId, toDBid NodeList)
where where
query :: DPS.Query query :: DPS.Query
query = [sql| query = [sql|
...@@ -103,8 +103,8 @@ triggerUpdateAdd lId = execPGSQuery query (lId, toDBid NodeList) ...@@ -103,8 +103,8 @@ triggerUpdateAdd lId = execPGSQuery query (lId, toDBid NodeList)
|] |]
triggerUpdateDel :: MasterListId -> DBCmd err Int64 triggerUpdateDel :: MasterListId -> DBUpdate err Int64
triggerUpdateDel lId = execPGSQuery query (lId, toDBid NodeList) triggerUpdateDel lId = mkPGUpdate query (lId, toDBid NodeList)
where where
query :: DPS.Query query :: DPS.Query
query = [sql| query = [sql|
...@@ -145,8 +145,8 @@ triggerUpdateDel lId = execPGSQuery query (lId, toDBid NodeList) ...@@ -145,8 +145,8 @@ triggerUpdateDel lId = execPGSQuery query (lId, toDBid NodeList)
triggerDeleteCount :: MasterListId -> DBCmd err Int64 triggerDeleteCount :: MasterListId -> DBUpdate err Int64
triggerDeleteCount lId = execPGSQuery query (lId, toDBid NodeList) triggerDeleteCount lId = mkPGUpdate query (lId, toDBid NodeList)
where where
query :: DPS.Query query :: DPS.Query
query = [sql| query = [sql|
......
{-# LANGUAGE ConstraintKinds #-}
module Gargantext.Database.Class where
import Control.Lens (Getter)
import Control.Monad.Random ( MonadRandom )
import Control.Monad.Trans.Control (MonadBaseControl)
import Data.Pool (Pool)
import Database.PostgreSQL.Simple (Connection)
import Gargantext.Core.Notifications.CentralExchange.Types qualified as CET
import Gargantext.Core.Config (HasConfig(..))
import Gargantext.Core.Mail.Types (HasMail)
import Gargantext.Core.NLP (HasNLPServer)
import Gargantext.Prelude
-- $typesAndConstraints
--
-- The names of the constraints and types in this module are chosen based on
-- the following guidelines:
-- * By default, constraints are relatively lenient. Stricter constraints are
-- obtained by appending the `Extra` suffix to the minimal constraint name.
-- * `IsDBEnv(Extra)` applies to the environment; the basic constraint allows
-- access to the database, and the `Extra` variant offers some more
-- capabilities such as access to mail.
-- * `IsCmd` is the basic constraint for command monads. Append `DB` to it to get
-- a monad of commands that can talk to the database. Append `Extra` to get
-- the ability to send mail, make use of the NLP server and deal with central
-- exchange notifications. Append `Random` to get access to randomness.
-- * Existential versions of the constraints bear the same name as the constraint
-- they are based on, but without the `Is` prefix.
class HasConnectionPool env where
connPool :: Getter env (Pool Connection)
instance HasConnectionPool (Pool Connection) where
connPool = identity
-- | The most basic constraints for an environment with a database.
-- If possible, try to not add more constraints here. When performing
-- a query/update on the DB, one shouldn't need more than being able to
-- fetch from the underlying 'env' the connection pool and access the
-- 'GargConfig' for some sensible defaults to store into the DB.
type IsDBEnv env =
( HasConnectionPool env
, HasConfig env
)
-- | Constraints for a full-fledged environment, with a database, mail exchange,
-- NLP processing, notifications.
type IsDBEnvExtra env =
( IsDBEnv env
, HasMail env
, HasNLPServer env
, CET.HasCentralExchangeNotification env
)
-- | The most general constraints for commands. To interact with the database,
-- or access extra features (such as sending mail), you'll need to add some more
-- constraints (see the rest of this module)
type IsCmd env err m =
( MonadReader env m
, MonadError err m
, MonadBaseControl IO m
)
-- | Only the /minimum/ amount of class constraints required
-- to use the Gargantext Database. It's important, to ease testability,
-- that these constraints stays as few as possible.
type IsDBCmd env err m =
( IsCmd env err m
, IsDBEnv env
)
-- | Full-fledged command class. Types in this class provide commands that can
-- interact with the database, perform NLP processing, etc.
type IsDBCmdExtra env err m =
( IsCmd env err m
, IsDBEnvExtra env
)
-- | Basic command with access to randomness. It feels a little ad hoc to have
-- such a constraint instead of substituting it (and its counterpart existential
-- type `CmdRandom`) with its definition every time it appears in the codebase,
-- but I tried to doing that substitution and it wasn't so easy.
type IsCmdRandom env err m =
( IsCmd env err m
, MonadRandom m
)
-- | Barebones command type, without any built-in ability to interact with the
-- database or do stuff like email exchanges.
type Cmd env err a = forall m. IsCmd env err m => m a
-- | Basic command type with access to randomness
type CmdRandom env err a = forall m. IsCmdRandom env err m => m a
-- | Command type that allows for interaction with the database.
type DBCmd err a = forall m env. IsDBCmd env err m => m a
-- | Command type that allows for interaction with the database. Similar to
-- `DBCmd`, except you can constraint the environment type some more.
type DBCmdWithEnv env err a = forall m. IsDBCmd env err m => m a
-- | Full-fledged command types, with access to the database, mail, NLP
-- processing and central exchange notifications.
type DBCmdExtra err a = forall m env. IsDBCmdExtra env err m => m a
This diff is collapsed.
...@@ -21,7 +21,7 @@ import Gargantext.Core.Types ...@@ -21,7 +21,7 @@ import Gargantext.Core.Types
import Gargantext.Core.Types.Query (Limit, Offset) import Gargantext.Core.Types.Query (Limit, Offset)
import Gargantext.Database.Admin.Types.Hyperdata.Any ( HyperdataAny ) import Gargantext.Database.Admin.Types.Hyperdata.Any ( HyperdataAny )
import Gargantext.Database.Admin.Types.Hyperdata.Document ( HyperdataDocument, HyperdataDocumentV3 ) import Gargantext.Database.Admin.Types.Hyperdata.Document ( HyperdataDocument, HyperdataDocumentV3 )
import Gargantext.Database.Prelude (DBCmd, JSONB, runOpaQuery) import Gargantext.Database.Prelude
import Gargantext.Database.Query.Filter (limit', offset') import Gargantext.Database.Query.Filter (limit', offset')
import Gargantext.Database.Query.Table.Node.Error ( HasNodeError, nodeError, NodeError(NoContextFound) ) import Gargantext.Database.Query.Table.Node.Error ( HasNodeError, nodeError, NodeError(NoContextFound) )
import Gargantext.Database.Schema.Context import Gargantext.Database.Schema.Context
...@@ -31,9 +31,9 @@ import Prelude hiding (null, id, map, sum) ...@@ -31,9 +31,9 @@ import Prelude hiding (null, id, map, sum)
getContextWith :: (HasNodeError err, JSONB a) getContextWith :: (HasNodeError err, JSONB a)
=> ContextId -> proxy a -> DBCmd err (Node a) => ContextId -> proxy a -> DBQuery err x (Node a)
getContextWith cId _ = do getContextWith cId _ = do
maybeContext <- headMay <$> runOpaQuery (selectContext (pgContextId cId)) maybeContext <- headMay <$> mkOpaQuery (selectContext (pgContextId cId))
case maybeContext of case maybeContext of
Nothing -> nodeError (NoContextFound cId) Nothing -> nodeError (NoContextFound cId)
Just r -> pure $ context2node r Just r -> pure $ context2node r
...@@ -47,8 +47,8 @@ selectContext id' = proc () -> do ...@@ -47,8 +47,8 @@ selectContext id' = proc () -> do
restrict -< _context_id row .== id' restrict -< _context_id row .== id'
returnA -< row returnA -< row
runGetContexts :: Select ContextRead -> DBCmd err [Context HyperdataAny] runGetContexts :: Select ContextRead -> DBQuery err x [Context HyperdataAny]
runGetContexts = runOpaQuery runGetContexts = mkOpaQuery
------------------------------------------------------------------------ ------------------------------------------------------------------------
------------------------------------------------------------------------ ------------------------------------------------------------------------
...@@ -80,12 +80,12 @@ selectContextsWith' parentId maybeContextType = proc () -> do ...@@ -80,12 +80,12 @@ selectContextsWith' parentId maybeContextType = proc () -> do
------------------------------------------------------------------------ ------------------------------------------------------------------------
getDocumentsV3WithParentId :: HasDBid NodeType => NodeId -> DBCmd err [Context HyperdataDocumentV3] getDocumentsV3WithParentId :: HasDBid NodeType => NodeId -> DBQuery err x [Context HyperdataDocumentV3]
getDocumentsV3WithParentId n = runOpaQuery $ selectContextsWith' n (Just NodeDocument) getDocumentsV3WithParentId n = mkOpaQuery $ selectContextsWith' n (Just NodeDocument)
-- TODO: merge with getDocumentsWithParentId by having a class IsHyperdataDocument -- TODO: merge with getDocumentsWithParentId by having a class IsHyperdataDocument
getDocumentsWithParentId :: HasDBid NodeType => NodeId -> DBCmd err [Context HyperdataDocument] getDocumentsWithParentId :: HasDBid NodeType => NodeId -> DBQuery err x [Context HyperdataDocument]
getDocumentsWithParentId n = runOpaQuery $ selectContextsWith' n (Just NodeDocument) getDocumentsWithParentId n = mkOpaQuery $ selectContextsWith' n (Just NodeDocument)
------------------------------------------------------------------------ ------------------------------------------------------------------------
selectContextsWithParentID :: NodeId -> Select ContextRead selectContextsWithParentID :: NodeId -> Select ContextRead
...@@ -99,8 +99,8 @@ selectContextsWithParentID n = proc () -> do ...@@ -99,8 +99,8 @@ selectContextsWithParentID n = proc () -> do
-- | Example of use: -- | Example of use:
-- runCmdReplEasy (getNodesWithType NodeList (Proxy :: Proxy HyperdataList)) -- runCmdReplEasy (getNodesWithType NodeList (Proxy :: Proxy HyperdataList))
getContextsWithType :: (HasNodeError err, JSONB a, HasDBid NodeType) getContextsWithType :: (HasNodeError err, JSONB a, HasDBid NodeType)
=> NodeType -> proxy a -> DBCmd err [Context a] => NodeType -> proxy a -> DBQuery err x [Context a]
getContextsWithType nt _ = runOpaQuery $ selectContextsWithType nt getContextsWithType nt _ = mkOpaQuery $ selectContextsWithType nt
where where
selectContextsWithType :: HasDBid NodeType selectContextsWithType :: HasDBid NodeType
=> NodeType -> Select ContextRead => NodeType -> Select ContextRead
...@@ -110,9 +110,9 @@ getContextsWithType nt _ = runOpaQuery $ selectContextsWithType nt ...@@ -110,9 +110,9 @@ getContextsWithType nt _ = runOpaQuery $ selectContextsWithType nt
returnA -< row returnA -< row
getContextsIdWithType :: (HasNodeError err, HasDBid NodeType) getContextsIdWithType :: (HasNodeError err, HasDBid NodeType)
=> NodeType -> DBCmd err [ContextId] => NodeType -> DBQuery err x [ContextId]
getContextsIdWithType nt = do getContextsIdWithType nt = do
ns <- runOpaQuery $ selectContextsIdWithType nt ns <- mkOpaQuery $ selectContextsIdWithType nt
pure (map UnsafeMkContextId ns) pure (map UnsafeMkContextId ns)
selectContextsIdWithType :: HasDBid NodeType selectContextsIdWithType :: HasDBid NodeType
......
This diff is collapsed.
...@@ -23,7 +23,7 @@ import Gargantext.Core.Types ...@@ -23,7 +23,7 @@ import Gargantext.Core.Types
import Gargantext.Core.Types.Query (Limit, Offset) import Gargantext.Core.Types.Query (Limit, Offset)
import Gargantext.Database.Admin.Types.Hyperdata.Contact ( HyperdataContact ) import Gargantext.Database.Admin.Types.Hyperdata.Contact ( HyperdataContact )
import Gargantext.Database.Admin.Types.Hyperdata.Document ( HyperdataDocument ) import Gargantext.Database.Admin.Types.Hyperdata.Document ( HyperdataDocument )
import Gargantext.Database.Prelude (DBCmd, JSONB, runCountOpaQuery, runOpaQuery, runPGSQuery) import Gargantext.Database.Prelude
import Gargantext.Database.Query.Filter ( limit', offset' ) import Gargantext.Database.Query.Filter ( limit', offset' )
import Gargantext.Database.Query.Table.NodeContext ( NodeContextPoly(NodeContext), queryNodeContextTable ) import Gargantext.Database.Query.Table.NodeContext ( NodeContextPoly(NodeContext), queryNodeContextTable )
import Gargantext.Database.Schema.Context import Gargantext.Database.Schema.Context
...@@ -33,12 +33,12 @@ import Opaleye ...@@ -33,12 +33,12 @@ import Opaleye
-- TODO getAllTableDocuments -- TODO getAllTableDocuments
getAllDocuments :: HasDBid NodeType => ParentId -> DBCmd err (TableResult (Node HyperdataDocument)) getAllDocuments :: HasDBid NodeType => ParentId -> DBQuery err x (TableResult (Node HyperdataDocument))
getAllDocuments pId = getAllChildren pId (Proxy :: Proxy HyperdataDocument) getAllDocuments pId = getAllChildren pId (Proxy :: Proxy HyperdataDocument)
(Just NodeDocument) (Just NodeDocument)
-- TODO getAllTableContacts -- TODO getAllTableContacts
getAllContacts :: HasDBid NodeType => ParentId -> DBCmd err (TableResult (Node HyperdataContact)) getAllContacts :: HasDBid NodeType => ParentId -> DBQuery err x (TableResult (Node HyperdataContact))
getAllContacts pId = getAllChildren pId (Proxy :: Proxy HyperdataContact) getAllContacts pId = getAllChildren pId (Proxy :: Proxy HyperdataContact)
(Just NodeContact) (Just NodeContact)
...@@ -46,7 +46,7 @@ getAllChildren :: (JSONB a, HasDBid NodeType) ...@@ -46,7 +46,7 @@ getAllChildren :: (JSONB a, HasDBid NodeType)
=> ParentId => ParentId
-> proxy a -> proxy a
-> Maybe NodeType -> Maybe NodeType
-> DBCmd err (NodeTableResult a) -> DBQuery err x (NodeTableResult a)
getAllChildren pId p maybeNodeType = getChildren pId p maybeNodeType Nothing Nothing getAllChildren pId p maybeNodeType = getChildren pId p maybeNodeType Nothing Nothing
...@@ -56,7 +56,7 @@ getChildren :: (JSONB a, HasDBid NodeType) ...@@ -56,7 +56,7 @@ getChildren :: (JSONB a, HasDBid NodeType)
-> Maybe NodeType -> Maybe NodeType
-> Maybe Offset -> Maybe Offset
-> Maybe Limit -> Maybe Limit
-> DBCmd err (NodeTableResult a) -> DBQuery err x (NodeTableResult a)
getChildren pId p t@(Just NodeDocument) maybeOffset maybeLimit = getChildrenContext pId p t maybeOffset maybeLimit getChildren pId p t@(Just NodeDocument) maybeOffset maybeLimit = getChildrenContext pId p t maybeOffset maybeLimit
getChildren pId p t@(Just NodeContact ) maybeOffset maybeLimit = getChildrenContext pId p t maybeOffset maybeLimit getChildren pId p t@(Just NodeContact ) maybeOffset maybeLimit = getChildrenContext pId p t maybeOffset maybeLimit
getChildren a b c d e = getChildrenNode a b c d e getChildren a b c d e = getChildrenNode a b c d e
...@@ -64,8 +64,8 @@ getChildren a b c d e = getChildrenNode a b c d e ...@@ -64,8 +64,8 @@ getChildren a b c d e = getChildrenNode a b c d e
-- | Get the list of (IDs of) children of a given node (ID) -- | Get the list of (IDs of) children of a given node (ID)
getChildrenByParentId :: NodeId -- ^ ID of the parent node getChildrenByParentId :: NodeId -- ^ ID of the parent node
-> DBCmd err [NodeId] -- ^ List of IDs of the children nodes -> DBQuery err x [NodeId] -- ^ List of IDs of the children nodes
getChildrenByParentId parentId = runPGSQuery getChildrenByParentId parentId = mkPGQuery
[sql| SELECT id FROM public.nodes WHERE parent_id = ?; |] [sql| SELECT id FROM public.nodes WHERE parent_id = ?; |]
parentId parentId
...@@ -76,16 +76,16 @@ getChildrenNode :: (JSONB a, HasDBid NodeType) ...@@ -76,16 +76,16 @@ getChildrenNode :: (JSONB a, HasDBid NodeType)
-> Maybe NodeType -> Maybe NodeType
-> Maybe Offset -> Maybe Offset
-> Maybe Limit -> Maybe Limit
-> DBCmd err (NodeTableResult a) -> DBQuery err x (NodeTableResult a)
getChildrenNode pId _ maybeNodeType maybeOffset maybeLimit = do getChildrenNode pId _ maybeNodeType maybeOffset maybeLimit = do
-- printDebug "getChildrenNode" (pId, maybeNodeType) -- printDebug "getChildrenNode" (pId, maybeNodeType)
let query = selectChildrenNode pId maybeNodeType let query = selectChildrenNode pId maybeNodeType
docs <- runOpaQuery docs <- mkOpaQuery
$ limit' maybeLimit $ limit' maybeLimit
$ offset' maybeOffset $ offset' maybeOffset
$ orderBy (asc _node_id) $ orderBy (asc _node_id)
$ query $ query
docCount <- runCountOpaQuery query docCount <- mkOpaCountQuery query
pure $ TableResult { tr_docs = docs, tr_count = docCount } pure $ TableResult { tr_docs = docs, tr_count = docCount }
...@@ -107,18 +107,18 @@ getChildrenContext :: (JSONB a, HasDBid NodeType) ...@@ -107,18 +107,18 @@ getChildrenContext :: (JSONB a, HasDBid NodeType)
-> Maybe NodeType -> Maybe NodeType
-> Maybe Offset -> Maybe Offset
-> Maybe Limit -> Maybe Limit
-> DBCmd err (NodeTableResult a) -> DBQuery err x (NodeTableResult a)
getChildrenContext pId _ maybeNodeType maybeOffset maybeLimit = do getChildrenContext pId _ maybeNodeType maybeOffset maybeLimit = do
-- printDebug "getChildrenContext" (pId, maybeNodeType) -- printDebug "getChildrenContext" (pId, maybeNodeType)
let query = selectChildren' pId maybeNodeType let query = selectChildren' pId maybeNodeType
docs <- runOpaQuery docs <- mkOpaQuery
$ limit' maybeLimit $ limit' maybeLimit
$ offset' maybeOffset $ offset' maybeOffset
$ orderBy (asc _context_id) $ orderBy (asc _context_id)
$ query $ query
docCount <- runCountOpaQuery query docCount <- mkOpaCountQuery query
pure $ TableResult { tr_docs = map context2node docs, tr_count = docCount } pure $ TableResult { tr_docs = map context2node docs, tr_count = docCount }
......
...@@ -68,7 +68,7 @@ import Gargantext.Core (HasDBid(toDBid)) ...@@ -68,7 +68,7 @@ import Gargantext.Core (HasDBid(toDBid))
import Gargantext.Database.Admin.Types.Hyperdata.Contact ( HyperdataContact ) import Gargantext.Database.Admin.Types.Hyperdata.Contact ( HyperdataContact )
import Gargantext.Database.Admin.Types.Hyperdata.Document ( HyperdataDocument(..) ) import Gargantext.Database.Admin.Types.Hyperdata.Document ( HyperdataDocument(..) )
import Gargantext.Database.Admin.Types.Node import Gargantext.Database.Admin.Types.Node
import Gargantext.Database.Prelude (runPGSQuery, DBCmd{-, formatPGSQuery-}) import Gargantext.Database.Prelude
import Gargantext.Database.Schema.Node (NodePoly(..)) import Gargantext.Database.Schema.Node (NodePoly(..))
import Gargantext.Defaults qualified as Defaults import Gargantext.Defaults qualified as Defaults
import Gargantext.Prelude hiding (hash, toLower) import Gargantext.Prelude hiding (hash, toLower)
...@@ -87,8 +87,8 @@ import Database.PostgreSQL.Simple (formatQuery) ...@@ -87,8 +87,8 @@ import Database.PostgreSQL.Simple (formatQuery)
-- ParentId : folder ID which is parent of the inserted documents -- ParentId : folder ID which is parent of the inserted documents
-- Administrator of the database has to create a uniq index as following SQL command: -- Administrator of the database has to create a uniq index as following SQL command:
-- `create unique index on contexts table (typename, parent_id, (hyperdata ->> 'uniqId'));` -- `create unique index on contexts table (typename, parent_id, (hyperdata ->> 'uniqId'));`
insertDb :: (InsertDb a, HasDBid NodeType) => UserId -> Maybe ParentId -> [a] -> DBCmd err [ReturnId] insertDb :: (InsertDb a, HasDBid NodeType) => UserId -> Maybe ParentId -> [a] -> DBQuery err x [ReturnId]
insertDb u p = runPGSQuery queryInsert . Only . Values fields . map (insertDb' u p) insertDb u p as = mkPGQuery queryInsert (Only . Values fields $ map (insertDb' u p) as)
where where
fields = map (QualifiedIdentifier Nothing) inputSqlTypes fields = map (QualifiedIdentifier Nothing) inputSqlTypes
......
...@@ -135,15 +135,11 @@ instance ToJSON NodeError where ...@@ -135,15 +135,11 @@ instance ToJSON NodeError where
class HasNodeError e where class HasNodeError e where
_NodeError :: Prism' e NodeError _NodeError :: Prism' e NodeError
errorWith :: ( MonadError e m errorWith :: HasNodeError e => Text -> DBTx e r a
, HasNodeError e)
=> Text -> m a
errorWith x = nodeError (NodeError $ toException $ userError $ T.unpack x) errorWith x = nodeError (NodeError $ toException $ userError $ T.unpack x)
nodeError :: ( MonadError e m nodeError :: HasNodeError e => NodeError -> DBTx e r a
, HasNodeError e ) nodeError ne = dbFail $ _NodeError # ne
=> NodeError -> m a
nodeError ne = throwError $ _NodeError # ne
nodeCreationError :: ( MonadError e m, HasNodeError e) nodeCreationError :: ( MonadError e m, HasNodeError e)
=> NodeCreationError => NodeCreationError
......
...@@ -68,13 +68,13 @@ queryNodeContextTable :: Select NodeContextRead ...@@ -68,13 +68,13 @@ queryNodeContextTable :: Select NodeContextRead
queryNodeContextTable = selectTable nodeContextTable queryNodeContextTable = selectTable nodeContextTable
-- | not optimized (get all ngrams without filters) -- | not optimized (get all ngrams without filters)
_nodesContexts :: DBCmd err [NodeContext] _nodesContexts :: DBQuery err x [NodeContext]
_nodesContexts = runOpaQuery queryNodeContextTable _nodesContexts = mkOpaQuery queryNodeContextTable
------------------------------------------------------------------------ ------------------------------------------------------------------------
-- | Basic NodeContext tools -- | Basic NodeContext tools
getNodeContexts :: NodeId -> DBCmd err [NodeContext] getNodeContexts :: NodeId -> DBQuery err x [NodeContext]
getNodeContexts n = runOpaQuery (selectNodeContexts $ pgNodeId n) getNodeContexts n = mkOpaQuery (selectNodeContexts $ pgNodeId n)
where where
selectNodeContexts :: Field SqlInt4 -> Select NodeContextRead selectNodeContexts :: Field SqlInt4 -> Select NodeContextRead
selectNodeContexts n' = proc () -> do selectNodeContexts n' = proc () -> do
...@@ -83,9 +83,9 @@ getNodeContexts n = runOpaQuery (selectNodeContexts $ pgNodeId n) ...@@ -83,9 +83,9 @@ getNodeContexts n = runOpaQuery (selectNodeContexts $ pgNodeId n)
returnA -< ns returnA -< ns
getNodeContext :: HasNodeError err => ContextId -> NodeId -> DBCmd err NodeContext getNodeContext :: HasNodeError err => ContextId -> NodeId -> DBQuery err x NodeContext
getNodeContext c n = do getNodeContext c n = do
maybeNodeContext <- headMay <$> runOpaQuery (selectNodeContext (pgContextId c) (pgNodeId n)) maybeNodeContext <- headMay <$> mkOpaQuery (selectNodeContext (pgContextId c) (pgNodeId n))
case maybeNodeContext of case maybeNodeContext of
Nothing -> nodeError (NoContextFound c) Nothing -> nodeError (NoContextFound c)
Just r -> pure r Just r -> pure r
...@@ -97,9 +97,9 @@ getNodeContext c n = do ...@@ -97,9 +97,9 @@ getNodeContext c n = do
restrict -< _nc_node_id ns .== n' restrict -< _nc_node_id ns .== n'
returnA -< ns returnA -< ns
updateNodeContextCategory :: ContextId -> NodeId -> Int -> DBCmd err Int64 updateNodeContextCategory :: ContextId -> NodeId -> Int -> DBUpdate err Int64
updateNodeContextCategory cId nId cat = do updateNodeContextCategory cId nId cat = do
execPGSQuery upScore (cat, cId, nId) mkPGUpdate upScore (cat, cId, nId)
where where
upScore :: PGS.Query upScore :: PGS.Query
upScore = [sql| UPDATE nodes_contexts upScore = [sql| UPDATE nodes_contexts
...@@ -118,9 +118,9 @@ data ContextForNgrams = ...@@ -118,9 +118,9 @@ data ContextForNgrams =
getContextsForNgrams :: HasNodeError err getContextsForNgrams :: HasNodeError err
=> NodeId => NodeId
-> [Int] -> [Int]
-> DBCmd err [ContextForNgrams] -> DBQuery err x [ContextForNgrams]
getContextsForNgrams cId ngramsIds = do getContextsForNgrams cId ngramsIds = do
res <- runPGSQuery query (cId, PGS.In ngramsIds) res <- mkPGQuery query (cId, PGS.In ngramsIds)
pure $ (\( _cfn_nodeId pure $ (\( _cfn_nodeId
, _cfn_hash , _cfn_hash
, _cfn_userId , _cfn_userId
...@@ -152,10 +152,10 @@ getContextsForNgramsTerms :: HasNodeError err ...@@ -152,10 +152,10 @@ getContextsForNgramsTerms :: HasNodeError err
=> NodeId => NodeId
-> [Text] -> [Text]
-> Maybe Bool -> Maybe Bool
-> DBCmd err [ContextForNgramsTerms] -> DBQuery err x [ContextForNgramsTerms]
getContextsForNgramsTerms cId ngramsTerms (Just True) = do getContextsForNgramsTerms cId ngramsTerms (Just True) = do
let terms_length = length ngramsTerms let terms_length = length ngramsTerms
res <- runPGSQuery query (cId, PGS.In ngramsTerms, terms_length) res <- mkPGQuery query (cId, PGS.In ngramsTerms, terms_length)
pure $ (\( _cfnt_nodeId pure $ (\( _cfnt_nodeId
, _cfnt_hash , _cfnt_hash
, _cfnt_nodeTypeId , _cfnt_nodeTypeId
...@@ -198,7 +198,7 @@ getContextsForNgramsTerms cId ngramsTerms (Just True) = do ...@@ -198,7 +198,7 @@ getContextsForNgramsTerms cId ngramsTerms (Just True) = do
|] |]
getContextsForNgramsTerms cId ngramsTerms _ = do getContextsForNgramsTerms cId ngramsTerms _ = do
res <- runPGSQuery query (cId, PGS.In ngramsTerms) res <- mkPGQuery query (cId, PGS.In ngramsTerms)
pure $ (\( _cfnt_nodeId pure $ (\( _cfnt_nodeId
, _cfnt_hash , _cfnt_hash
, _cfnt_nodeTypeId , _cfnt_nodeTypeId
...@@ -246,9 +246,9 @@ getContextsForNgramsTerms cId ngramsTerms _ = do ...@@ -246,9 +246,9 @@ getContextsForNgramsTerms cId ngramsTerms _ = do
getContextNgrams :: HasNodeError err getContextNgrams :: HasNodeError err
=> NodeId => NodeId
-> NodeId -> NodeId
-> DBCmd err [Text] -> DBQuery err x [Text]
getContextNgrams contextId listId = do getContextNgrams contextId listId = do
res <- runPGSQuery query (contextId, listId) res <- mkPGQuery query (contextId, listId)
pure $ (\(PGS.Only term) -> term) <$> res pure $ (\(PGS.Only term) -> term) <$> res
where where
...@@ -270,9 +270,9 @@ getContextNgrams contextId listId = do ...@@ -270,9 +270,9 @@ getContextNgrams contextId listId = do
getContextNgramsMatchingFTS :: HasNodeError err getContextNgramsMatchingFTS :: HasNodeError err
=> ContextId => ContextId
-> NodeId -> NodeId
-> DBCmd err [Text] -> DBQuery err x [Text]
getContextNgramsMatchingFTS contextId listId = do getContextNgramsMatchingFTS contextId listId = do
res <- runPGSQuery query (listId, contextId) res <- mkPGQuery query (listId, contextId)
pure $ (\(PGS.Only term) -> term) <$> res pure $ (\(PGS.Only term) -> term) <$> res
where where
...@@ -299,9 +299,8 @@ getContextNgramsMatchingFTS contextId listId = do ...@@ -299,9 +299,8 @@ getContextNgramsMatchingFTS contextId listId = do
AND (contexts.search @@ plainto_tsquery(ngrams.terms) AND (contexts.search @@ plainto_tsquery(ngrams.terms)
OR contexts.search @@ plainto_tsquery('french', ngrams.terms)) |] OR contexts.search @@ plainto_tsquery('french', ngrams.terms)) |]
------------------------------------------------------------------------ ------------------------------------------------------------------------
insertNodeContext :: [NodeContext] -> DBCmd err Int insertNodeContext :: [NodeContext] -> DBUpdate err Int
insertNodeContext ns = mkCmd $ \conn -> fromIntegral <$> (runInsert conn insertNodeContext ns = fromIntegral <$> mkOpaInsert (Insert nodeContextTable ns' rCount (Just doNothing))
$ Insert nodeContextTable ns' rCount (Just doNothing))
where where
ns' :: [NodeContextWrite] ns' :: [NodeContextWrite]
ns' = map (\(NodeContext i n c x y) ns' = map (\(NodeContext i n c x y)
...@@ -317,9 +316,8 @@ insertNodeContext ns = mkCmd $ \conn -> fromIntegral <$> (runInsert conn ...@@ -317,9 +316,8 @@ insertNodeContext ns = mkCmd $ \conn -> fromIntegral <$> (runInsert conn
type Node_Id = NodeId type Node_Id = NodeId
type Context_Id = NodeId type Context_Id = NodeId
deleteNodeContext :: Node_Id -> Context_Id -> DBCmd err Int deleteNodeContext :: Node_Id -> Context_Id -> DBUpdate err Int64
deleteNodeContext n c = mkCmd $ \conn -> deleteNodeContext n c = mkOpaDelete $
fromIntegral <$> runDelete conn
(Delete nodeContextTable (Delete nodeContextTable
(\(NodeContext _ n_id c_id _ _) -> n_id .== pgNodeId n (\(NodeContext _ n_id c_id _ _) -> n_id .== pgNodeId n
.&& c_id .== pgNodeId c .&& c_id .== pgNodeId c
...@@ -329,9 +327,9 @@ deleteNodeContext n c = mkCmd $ \conn -> ...@@ -329,9 +327,9 @@ deleteNodeContext n c = mkCmd $ \conn ->
------------------------------------------------------------------------ ------------------------------------------------------------------------
-- | Favorite management -- | Favorite management
nodeContextsCategory :: [(CorpusId, DocId, Int)] -> DBCmd err [Int] nodeContextsCategory :: [(CorpusId, DocId, Int)] -> DBUpdate err [Int]
nodeContextsCategory inputData = map (\(PGS.Only a) -> a) nodeContextsCategory inputData = map (\(PGS.Only a) -> a)
<$> runPGSQuery catSelect (PGS.Only $ Values fields inputData) <$> mkPGUpdateReturningMany catSelect (PGS.Only $ Values fields inputData)
where where
fields = map (QualifiedIdentifier Nothing) ["int4","int4","int4"] fields = map (QualifiedIdentifier Nothing) ["int4","int4","int4"]
catSelect :: PGS.Query catSelect :: PGS.Query
...@@ -345,9 +343,9 @@ nodeContextsCategory inputData = map (\(PGS.Only a) -> a) ...@@ -345,9 +343,9 @@ nodeContextsCategory inputData = map (\(PGS.Only a) -> a)
------------------------------------------------------------------------ ------------------------------------------------------------------------
-- | Score management -- | Score management
nodeContextsScore :: [(CorpusId, DocId, Int)] -> DBCmd err [Int] nodeContextsScore :: [(CorpusId, DocId, Int)] -> DBUpdate err [Int]
nodeContextsScore inputData = map (\(PGS.Only a) -> a) nodeContextsScore inputData = map (\(PGS.Only a) -> a)
<$> runPGSQuery catScore (PGS.Only $ Values fields inputData) <$> mkPGUpdateReturningMany catScore (PGS.Only $ Values fields inputData)
where where
fields = map (QualifiedIdentifier Nothing) ["int4","int4","int4"] fields = map (QualifiedIdentifier Nothing) ["int4","int4","int4"]
catScore :: PGS.Query catScore :: PGS.Query
...@@ -370,8 +368,8 @@ nodeContextsScore inputData = map (\(PGS.Only a) -> a) ...@@ -370,8 +368,8 @@ nodeContextsScore inputData = map (\(PGS.Only a) -> a)
-- nc.node_id = 88 -- nc.node_id = 88
-- and nc.category >= 1 -- and nc.category >= 1
-- and c.typename = 4 -- and c.typename = 4
selectCountDocs :: HasDBid NodeType => CorpusId -> DBCmd err Int selectCountDocs :: HasDBid NodeType => CorpusId -> DBQuery err x Int
selectCountDocs cId = runCountOpaQuery (queryCountDocs cId) selectCountDocs cId = mkOpaCountQuery (countRows $ queryCountDocs cId)
where where
queryCountDocs cId' = proc () -> do queryCountDocs cId' = proc () -> do
(c, nc) <- joinInCorpus -< () (c, nc) <- joinInCorpus -< ()
...@@ -382,14 +380,14 @@ selectCountDocs cId = runCountOpaQuery (queryCountDocs cId) ...@@ -382,14 +380,14 @@ selectCountDocs cId = runCountOpaQuery (queryCountDocs cId)
-- | TODO use UTCTime fast -- | TODO use UTCTime fast
selectDocsDates :: HasDBid NodeType => CorpusId -> DBCmd err [Text] selectDocsDates :: HasDBid NodeType => CorpusId -> DBQuery err x [Text]
selectDocsDates cId = map (head' "selectDocsDates" . splitOn "-") selectDocsDates cId = map (head' "selectDocsDates" . splitOn "-")
<$> catMaybes <$> catMaybes
<$> map (view hd_publication_date) <$> map (view hd_publication_date)
<$> selectDocs cId <$> selectDocs cId
selectDocs :: HasDBid NodeType => CorpusId -> DBCmd err [HyperdataDocument] selectDocs :: HasDBid NodeType => CorpusId -> DBQuery err x [HyperdataDocument]
selectDocs cId = runOpaQuery (queryDocs cId) selectDocs cId = mkOpaQuery (queryDocs cId)
queryDocs :: HasDBid NodeType => CorpusId -> O.Select (Field SqlJsonb) queryDocs :: HasDBid NodeType => CorpusId -> O.Select (Field SqlJsonb)
queryDocs cId = proc () -> do queryDocs cId = proc () -> do
...@@ -399,8 +397,8 @@ queryDocs cId = proc () -> do ...@@ -399,8 +397,8 @@ queryDocs cId = proc () -> do
restrict -< (c ^. context_typename) .== sqlInt4 (toDBid NodeDocument) restrict -< (c ^. context_typename) .== sqlInt4 (toDBid NodeDocument)
returnA -< view (context_hyperdata) c returnA -< view (context_hyperdata) c
selectDocNodes :: HasDBid NodeType => CorpusId -> DBCmd err [Context HyperdataDocument] selectDocNodes :: HasDBid NodeType => CorpusId -> DBQuery err x [Context HyperdataDocument]
selectDocNodes cId = runOpaQuery (queryDocNodes cId) selectDocNodes cId = mkOpaQuery (queryDocNodes cId)
queryDocNodes :: HasDBid NodeType => CorpusId -> O.Select ContextRead queryDocNodes :: HasDBid NodeType => CorpusId -> O.Select ContextRead
queryDocNodes cId = proc () -> do queryDocNodes cId = proc () -> do
...@@ -414,8 +412,8 @@ queryDocNodes cId = proc () -> do ...@@ -414,8 +412,8 @@ queryDocNodes cId = proc () -> do
restrict -< (c ^. context_typename) .== sqlInt4 (toDBid NodeDocument) restrict -< (c ^. context_typename) .== sqlInt4 (toDBid NodeDocument)
returnA -< c returnA -< c
selectDocNodesOnlyId :: HasDBid NodeType => CorpusId -> DBCmd err [ContextOnlyId HyperdataDocument] selectDocNodesOnlyId :: HasDBid NodeType => CorpusId -> DBQuery err x [ContextOnlyId HyperdataDocument]
selectDocNodesOnlyId cId = runOpaQuery (queryDocNodesOnlyId cId) selectDocNodesOnlyId cId = mkOpaQuery (queryDocNodesOnlyId cId)
queryDocNodesOnlyId :: HasDBid NodeType => CorpusId -> O.Select ContextOnlyIdRead queryDocNodesOnlyId :: HasDBid NodeType => CorpusId -> O.Select ContextOnlyIdRead
queryDocNodesOnlyId cId = proc () -> do queryDocNodesOnlyId cId = proc () -> do
...@@ -441,8 +439,8 @@ joinOn1 = proc () -> do ...@@ -441,8 +439,8 @@ joinOn1 = proc () -> do
------------------------------------------------------------------------ ------------------------------------------------------------------------
selectPublicContexts :: HasDBid NodeType => (Hyperdata a, DefaultFromField SqlJsonb a) selectPublicContexts :: HasDBid NodeType => (Hyperdata a, DefaultFromField SqlJsonb a)
=> DBCmd err [(Node a, Maybe Int)] => DBQuery err x [(Node a, Maybe Int)]
selectPublicContexts = runOpaQuery (queryWithType NodeFolderPublic) selectPublicContexts = mkOpaQuery (queryWithType NodeFolderPublic)
queryWithType :: HasDBid NodeType => NodeType -> O.Select (NodeRead, MaybeFields (Field SqlInt4)) queryWithType :: HasDBid NodeType => NodeType -> O.Select (NodeRead, MaybeFields (Field SqlInt4))
queryWithType nt = proc () -> do queryWithType nt = proc () -> do
......
{-# LANGUAGE KindSignatures #-} {-# LANGUAGE KindSignatures #-}
{-# LANGUAGE LambdaCase #-} {-# LANGUAGE LambdaCase #-}
{-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}
module Gargantext.Database.Transactional ( module Gargantext.Database.Transactional (
DBOperation DBOperation
, DBTransactionOp -- opaque , DBTransactionOp -- opaque
...@@ -15,28 +16,32 @@ module Gargantext.Database.Transactional ( ...@@ -15,28 +16,32 @@ module Gargantext.Database.Transactional (
-- * Smart constructors -- * Smart constructors
, mkPGQuery , mkPGQuery
, mkPGUpdate , mkPGUpdate
, mkPGUpdateReturning , mkPGUpdateReturningOne
, mkPGUpdateReturningMany
, mkOpaQuery , mkOpaQuery
, mkOpaCountQuery
, mkOpaUpdate , mkOpaUpdate
, mkOpaInsert , mkOpaInsert
, mkOpaDelete
-- * Throwing errors (which allow rollbacks) -- * Throwing errors (which allow rollbacks)
, dbFail , dbFail
) where ) where
import Control.Exception.Safe qualified as Safe
import Control.Lens import Control.Lens
import Control.Monad.Base import Control.Monad.Base
import Control.Monad.Error.Class import Control.Monad.Error.Class
import Control.Monad.Free import Control.Monad.Free
import Control.Monad.Trans.Control (MonadBaseControl, control) import Control.Monad.Trans.Control (MonadBaseControl, control)
import Data.Int (Int64)
import Data.Pool (withResource, Pool) import Data.Pool (withResource, Pool)
import Data.Profunctor.Product.Default import Data.Profunctor.Product.Default
import Database.PostgreSQL.Simple qualified as PG import Database.PostgreSQL.Simple qualified as PG
import Database.PostgreSQL.Simple.Transaction qualified as PG import Database.PostgreSQL.Simple.Transaction qualified as PG
import Gargantext.Database.Prelude import Gargantext.Database.Class
import Opaleye import Opaleye
import Prelude import Prelude
import qualified Control.Exception.Safe as Safe
data DBOperation = DBRead | DBWrite data DBOperation = DBRead | DBWrite
...@@ -49,20 +54,24 @@ data DBTransactionOp err (r :: DBOperation) next where ...@@ -49,20 +54,24 @@ data DBTransactionOp err (r :: DBOperation) next where
PGQuery :: (PG.ToRow q, PG.FromRow a) => PG.Query -> q -> ([a] -> next) -> DBTransactionOp err r next PGQuery :: (PG.ToRow q, PG.FromRow a) => PG.Query -> q -> ([a] -> next) -> DBTransactionOp err r next
-- | A Postgres /write/, returning the number of affected rows. It can be used only in -- | A Postgres /write/, returning the number of affected rows. It can be used only in
-- 'DBWrite' transactions. -- 'DBWrite' transactions.
PGUpdate :: PG.ToRow a => PG.Query -> a -> (Int -> next) -> DBTransactionOp err DBWrite next PGUpdate :: PG.ToRow a => PG.Query -> a -> (Int64 -> next) -> DBTransactionOp err DBWrite next
-- | Unlike a 'PGUpdate' that returns the list of affected rows, this can be used -- | Unlike a 'PGUpdate' that returns the list of affected rows, this can be used
-- to write updates that returns a value via the \"RETURNING\" directive. It's the programmer's -- to write updates that returns a value via the \"RETURNING\" directive. It's the programmer's
-- responsibility to ensure that the SQL fragment contains it. -- responsibility to ensure that the SQL fragment contains it.
PGUpdateReturning :: (PG.ToRow q, PG.FromRow a) => PG.Query -> q -> (a -> next) -> DBTransactionOp err DBWrite next PGUpdateReturningMany :: (PG.ToRow q, PG.FromRow a) => PG.Query -> q -> ([a] -> next) -> DBTransactionOp err DBWrite next
-- | Ditto as above, but the contract is that the query has to return /exactly one/ result.
PGUpdateReturningOne :: (PG.ToRow q, PG.FromRow a) => PG.Query -> q -> (a -> next) -> DBTransactionOp err DBWrite next
-- | An Opaleye /read/, returning a list of results. The 'r' in the result is polymorphic -- | An Opaleye /read/, returning a list of results. The 'r' in the result is polymorphic
-- so that reads can be embedded in updates transactions. -- so that reads can be embedded in updates transactions.
OpaQuery :: Default FromFields fields a => Select fields -> ([a] -> next) -> DBTransactionOp err r next OpaQuery :: Default FromFields fields a => Select fields -> ([a] -> next) -> DBTransactionOp err r next
OpaCountQuery :: Select a -> (Int -> next) -> DBTransactionOp err r next
-- | An Opaleye /write/, returning a result depending on the input 'Insert'. It can be used only in -- | An Opaleye /write/, returning a result depending on the input 'Insert'. It can be used only in
-- 'DBWrite' transactions. -- 'DBWrite' transactions.
OpaInsert :: Insert a -> (a -> next) -> DBTransactionOp err DBWrite next OpaInsert :: Insert a -> (a -> next) -> DBTransactionOp err DBWrite next
-- | An Opaleye /write/, returning a result depending on the input 'Update'. It can be used only in -- | An Opaleye /write/, returning a result depending on the input 'Update'. It can be used only in
-- 'DBWrite' transactions. -- 'DBWrite' transactions.
OpaUpdate :: Update a -> (a -> next) -> DBTransactionOp err DBWrite next OpaUpdate :: Update a -> (a -> next) -> DBTransactionOp err DBWrite next
OpaDelete :: Delete a -> (a -> next) -> DBTransactionOp err DBWrite next
-- | Monadic failure for DB transactions. -- | Monadic failure for DB transactions.
DBFail :: err -> DBTransactionOp err r next DBFail :: err -> DBTransactionOp err r next
...@@ -80,13 +89,16 @@ type DBTxCmd err a = forall m env. (IsCmd env err m, HasConnectionPool env) => m ...@@ -80,13 +89,16 @@ type DBTxCmd err a = forall m env. (IsCmd env err m, HasConnectionPool env) => m
instance Functor (DBTransactionOp err r) where instance Functor (DBTransactionOp err r) where
fmap f = \case fmap f = \case
PGQuery q params cont -> PGQuery q params (f . cont) PGQuery q params cont -> PGQuery q params (f . cont)
PGUpdate q a cont -> PGUpdate q a (f . cont) PGUpdate q a cont -> PGUpdate q a (f . cont)
PGUpdateReturning q a cont -> PGUpdateReturning q a (f . cont) PGUpdateReturningOne q a cont -> PGUpdateReturningOne q a (f . cont)
OpaQuery sel cont -> OpaQuery sel (f . cont) PGUpdateReturningMany q a cont -> PGUpdateReturningMany q a (f . cont)
OpaInsert ins cont -> OpaInsert ins (f . cont) OpaQuery sel cont -> OpaQuery sel (f . cont)
OpaUpdate upd cont -> OpaUpdate upd (f . cont) OpaCountQuery sel cont -> OpaCountQuery sel (f . cont)
DBFail err -> DBFail err OpaInsert ins cont -> OpaInsert ins (f . cont)
OpaUpdate upd cont -> OpaUpdate upd (f . cont)
OpaDelete del cont -> OpaDelete del (f . cont)
DBFail err -> DBFail err
-- | Generalised version of 'withResource' to work over any unlifted monad. -- | Generalised version of 'withResource' to work over any unlifted monad.
-- For some reason 'resource-pool' removed this from version 0.3.0.0 onwards. -- For some reason 'resource-pool' removed this from version 0.3.0.0 onwards.
...@@ -132,13 +144,22 @@ runDBQuery (DBTx m) = do ...@@ -132,13 +144,22 @@ runDBQuery (DBTx m) = do
-- 'DBCmd'. -- 'DBCmd'.
evalOp :: PG.Connection -> DBTransactionOp err r a -> DBTxCmd err a evalOp :: PG.Connection -> DBTransactionOp err r a -> DBTxCmd err a
evalOp conn = \case evalOp conn = \case
PGQuery qr q cc -> cc <$> liftBase (PG.query conn qr q) PGQuery qr q cc -> cc <$> liftBase (PG.query conn qr q)
PGUpdate qr a cc -> cc <$> liftBase (fromIntegral <$> PG.execute conn qr a) PGUpdate qr a cc -> cc <$> liftBase (PG.execute conn qr a)
PGUpdateReturning qr a cc -> cc <$> liftBase (queryOne conn qr a) PGUpdateReturningOne qr a cc -> cc <$> liftBase (queryOne conn qr a)
OpaQuery sel cc -> cc <$> liftBase (runSelect conn sel) PGUpdateReturningMany qr a cc -> cc <$> liftBase (PG.query conn qr a)
OpaInsert ins cc -> cc <$> liftBase (runInsert conn ins) OpaQuery sel cc -> cc <$> liftBase (runSelect conn sel)
OpaUpdate upd cc -> cc <$> liftBase (runUpdate conn upd) OpaCountQuery sel cc -> cc <$> liftBase (evalOpaCountQuery conn sel)
DBFail err -> throwError err OpaInsert ins cc -> cc <$> liftBase (runInsert conn ins)
OpaUpdate upd cc -> cc <$> liftBase (runUpdate conn upd)
OpaDelete del cc -> cc <$> liftBase (runDelete conn del)
DBFail err -> throwError err
evalOpaCountQuery :: PG.Connection -> Select a -> IO Int
evalOpaCountQuery conn sel = do
counts <- runSelect conn $ countRows sel
-- countRows is guaranteed to return a list with exactly one row so DL.head is safe here
pure $ fromIntegral @Int64 @Int $ head counts
queryOne :: (PG.ToRow q, PG.FromRow r) => PG.Connection -> PG.Query -> q -> IO r queryOne :: (PG.ToRow q, PG.FromRow r) => PG.Connection -> PG.Query -> q -> IO r
queryOne conn q v = do queryOne conn q v = do
...@@ -161,19 +182,29 @@ mkPGQuery :: (PG.ToRow q, PG.FromRow a) ...@@ -161,19 +182,29 @@ mkPGQuery :: (PG.ToRow q, PG.FromRow a)
-> DBQuery err r [a] -> DBQuery err r [a]
mkPGQuery q a = DBTx $ liftF (PGQuery q a id) mkPGQuery q a = DBTx $ liftF (PGQuery q a id)
mkPGUpdate :: PG.ToRow a => PG.Query -> a -> DBUpdate err Int mkPGUpdate :: PG.ToRow a => PG.Query -> a -> DBUpdate err Int64
mkPGUpdate q a = DBTx $ liftF (PGUpdate q a id) mkPGUpdate q a = DBTx $ liftF (PGUpdate q a id)
mkPGUpdateReturning :: (PG.ToRow q, PG.FromRow a) => PG.Query -> q -> DBUpdate err a mkPGUpdateReturningOne :: (PG.ToRow q, PG.FromRow a) => PG.Query -> q -> DBUpdate err a
mkPGUpdateReturning q a = DBTx $ liftF (PGUpdateReturning q a id) mkPGUpdateReturningOne q a = DBTx $ liftF (PGUpdateReturningOne q a id)
mkPGUpdateReturningMany :: (PG.ToRow q, PG.FromRow a) => PG.Query -> q -> DBUpdate err [a]
mkPGUpdateReturningMany q a = DBTx $ liftF (PGUpdateReturningMany q a id)
mkOpaQuery :: Default FromFields fields a mkOpaQuery :: Default FromFields fields a
=> Select fields => Select fields
-> DBQuery err x [a] -> DBQuery err x [a]
mkOpaQuery s = DBTx $ liftF (OpaQuery s id) mkOpaQuery s = DBTx $ liftF (OpaQuery s id)
mkOpaCountQuery :: Select fields
-> DBQuery err x Int
mkOpaCountQuery s = DBTx $ liftF (OpaCountQuery s id)
mkOpaUpdate :: Update a -> DBUpdate err a mkOpaUpdate :: Update a -> DBUpdate err a
mkOpaUpdate a = DBTx $ liftF (OpaUpdate a id) mkOpaUpdate a = DBTx $ liftF (OpaUpdate a id)
mkOpaInsert :: Insert a -> DBUpdate err a mkOpaInsert :: Insert a -> DBUpdate err a
mkOpaInsert a = DBTx $ liftF (OpaInsert a id) mkOpaInsert a = DBTx $ liftF (OpaInsert a id)
mkOpaDelete :: Delete a -> DBUpdate err a
mkOpaDelete a = DBTx $ liftF (OpaDelete a id)
...@@ -146,17 +146,17 @@ getCounterById (CounterId cid) = do ...@@ -146,17 +146,17 @@ getCounterById (CounterId cid) = do
insertCounter :: DBUpdate IOException Counter insertCounter :: DBUpdate IOException Counter
insertCounter = do insertCounter = do
mkPGUpdateReturning [sql| INSERT INTO public.ggtx_test_counter_table(counter_value) VALUES(0) RETURNING id, counter_value|] () mkPGUpdateReturningOne [sql| INSERT INTO public.ggtx_test_counter_table(counter_value) VALUES(0) RETURNING id, counter_value|] ()
updateCounter :: CounterId -> Int -> DBUpdate IOException Counter updateCounter :: CounterId -> Int -> DBUpdate IOException Counter
updateCounter cid x = do updateCounter cid x = do
mkPGUpdateReturning [sql| UPDATE public.ggtx_test_counter_table SET counter_value = ? WHERE id = ? RETURNING *|] (x, cid) mkPGUpdateReturningOne [sql| UPDATE public.ggtx_test_counter_table SET counter_value = ? WHERE id = ? RETURNING *|] (x, cid)
-- | We deliberately write this as a composite operation. -- | We deliberately write this as a composite operation.
stepCounter :: CounterId -> DBUpdate IOException Counter stepCounter :: CounterId -> DBUpdate IOException Counter
stepCounter cid = do stepCounter cid = do
Counter{..} <- getCounterById cid Counter{..} <- getCounterById cid
mkPGUpdateReturning [sql| UPDATE public.ggtx_test_counter_table SET counter_value = ? WHERE id = ? RETURNING *|] (counterValue + 1, cid) mkPGUpdateReturningOne [sql| UPDATE public.ggtx_test_counter_table SET counter_value = ? WHERE id = ? RETURNING *|] (counterValue + 1, cid)
-- --
-- MAIN TESTS -- MAIN TESTS
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment