From 010decf8182eb9ce96d55a5d0c017ffcebd31d2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexandre=20Delano=C3=AB?= <devel+git@delanoe.org> Date: Fri, 15 Jun 2018 17:14:27 +0200 Subject: [PATCH] [BASQHL] first basic function and todo list. --- src/Gargantext/Core/Types/Node.hs | 3 + src/Gargantext/Database.hs | 110 ++++++++++++++++++++++++------ src/Gargantext/Database/Node.hs | 84 ++++++++++++++++++++--- src/Gargantext/Prelude.hs | 6 +- 4 files changed, 168 insertions(+), 35 deletions(-) diff --git a/src/Gargantext/Core/Types/Node.hs b/src/Gargantext/Core/Types/Node.hs index bee9ce8f..45650a60 100644 --- a/src/Gargantext/Core/Types/Node.hs +++ b/src/Gargantext/Core/Types/Node.hs @@ -265,6 +265,9 @@ data NodePoly id typename userId parentId name date hyperdata = Node { node_id } deriving (Show, Generic) $(deriveJSON (unPrefix "node_") ''NodePoly) + + + instance Arbitrary (NodePoly NodeId NodeTypeId (Maybe NodeUserId) NodeParentId NodeName UTCTime Value) where arbitrary = elements [Node 1 1 (Just 1) 1 "name" (jour 2018 01 01) (toJSON ("{}"::Text))] diff --git a/src/Gargantext/Database.hs b/src/Gargantext/Database.hs index 76f426c0..ab09ef10 100644 --- a/src/Gargantext/Database.hs +++ b/src/Gargantext/Database.hs @@ -12,7 +12,7 @@ Portability : POSIX * Which language to chose when working with a database ? To make it simple, instead of all common Object Relational Mapping (ORM) [1] strategy used nowadays inspired more by object logic than functional -logic, the semantics of BASHQL focus on the function first. +logic, the semantics of BASHQL with focus on the function first. * BASHQL focus on the function, i.e. use bash language function name, and make it with SQL behind the scene. Then BASHQL is inspired more @@ -57,40 +57,106 @@ AMS, and by SIAM. {-# LANGUAGE NoImplicitPrelude #-} module Gargantext.Database ( module Gargantext.Database.Utils - , ls') + , get + , ls , ls' + , home, home' + , post, post' + , del , del' + ) where import Gargantext.Core.Types +import Gargantext.Core.Types.Node import Gargantext.Database.Utils (connectGargandb) import Gargantext.Database.Node import Gargantext.Prelude import Database.PostgreSQL.Simple (Connection) - +import Data.Text (Text) import Opaleye hiding (FromField) import Data.Aeson --- type PWD = Node NodeId --- type Path = [PWD] - --- pwd :: [Node NodeId] -> +import Data.ByteString (ByteString) +import Data.List (last) +type UserId = Int +--type NodeId = Int + +-- List of NodeId +-- type PWD a = PWD UserId [a] +type PWD = [NodeId] + +-- | TODO get Children or Node +get :: Connection -> PWD -> IO [Node Value] +get _ [] = pure [] +get conn pwd = runQuery conn $ selectNodesWithParentID (last pwd) + +-- | Home, need to filter with UserId +home :: Connection -> IO PWD +home c = map node_id <$> getNodesWithParentId c 0 Nothing + +-- | ls == get Children +ls :: Connection -> PWD -> IO [Node Value] +ls = get + +-- | TODO +-- post User +-- post Dir +-- post Corpus Parent_id (Empty|MyData) +-- post CorpusWith +-- post List +post :: Connection -> PWD -> [NodeWrite'] -> IO Int64 +post _ [] _ = pure 0 +post _ _ [] = pure 0 +post c pth ns = mkNode c (last pth) ns + +rm :: Connection -> PWD -> [NodeId] -> IO Int +rm = del + +del :: Connection -> PWD -> [NodeId] -> IO Int +del _ [] _ = pure 0 +del _ _ [] = pure 0 +del c pth ns = deleteNodes c ns + +put :: Connection -> PWD -> [a] -> IO Int64 +put = undefined + +-- | TODO +-- cd (Home UserId) | (Node NodeId) +-- cd Path +-- jump NodeId +-- touch Dir +-------------------------------------------------------------- +-- Tests +-------------------------------------------------------------- -ls :: Connection -> Int -> IO [Node Value] -ls conn n = runQuery conn $ selectNodesWithParentID n +home' :: IO PWD +home' = do + c <- connectGargandb "gargantext.ini" + home c ls' :: IO [Node Value] -ls' = connectGargandb "gargantext.ini" >>= \c -> ls c 347474 +ls' = do + c <- connectGargandb "gargantext.ini" + h <- home c + ls c h + +post' :: IO Int64 +post' = do + c <- connectGargandb "gargantext.ini" + h <- home c + let userId = 1 + -- TODO semantic to achieve + -- post c h [ Corpus "name" "{}" Nothing + -- , Project "name" "{}" (Just [Corpus "test 2" "" Nothing]) + -- ] + post c h [ node userId (last h) Corpus "name" "{}" + , node userId (last h) Project "name" "{}" + ] + +del' :: [NodeId] -> IO Int +del' ns = do + c <- connectGargandb "gargantext.ini" + h <- home c + del c h ns --- ls' Maybe PWD --- cd (Home UserId) | (Node NodeId) - --- cd Path --- jump PWD - --- mk User --- mk Dir --- mk Corpus Parent_id (Empty|MyData) --- mk CorpusWith --- mk List --- touch Dir diff --git a/src/Gargantext/Database/Node.hs b/src/Gargantext/Database/Node.hs index b578ab36..d28e378a 100644 --- a/src/Gargantext/Database/Node.hs +++ b/src/Gargantext/Database/Node.hs @@ -21,6 +21,10 @@ Portability : POSIX module Gargantext.Database.Node where +import Data.ByteString (ByteString) +import GHC.Int (Int64) +import Data.Maybe +import Data.Time (UTCTime) import Database.PostgreSQL.Simple.FromField ( Conversion , ResultError(ConversionFailed) , FromField @@ -28,6 +32,7 @@ import Database.PostgreSQL.Simple.FromField ( Conversion , returnError ) import Prelude hiding (null, id, map, sum) +import Data.Time.Segment (jour, timesAfter, Granularity(D)) import Gargantext.Core.Types import Gargantext.Core.Types.Node (NodeType) @@ -46,7 +51,8 @@ import Data.Typeable (Typeable) import qualified Data.ByteString.Internal as DBI import Database.PostgreSQL.Simple (Connection) import Opaleye hiding (FromField) - +import Opaleye.Internal.QueryArr (Query(..)) +import qualified Data.Profunctor.Product as PP -- | Types for Node Database Management data PGTSVector @@ -89,7 +95,7 @@ fromField' field mb = do $(makeAdaptorAndInstance "pNode" ''NodePoly) -$(makeLensesWith abbreviatedFields ''NodePoly) +$(makeLensesWith abbreviatedFields ''NodePoly) nodeTable :: Table NodeWrite NodeRead @@ -105,12 +111,40 @@ nodeTable = Table "nodes" (pNode Node { node_id = optional "id" ) +nodeTable' :: Table (Maybe (Column PGInt4) + , Column PGInt4 + , Column PGInt4 + , Column PGInt4 + , Column PGText + ,Maybe (Column PGTimestamptz) + , Column PGJsonb + ) + ((Column PGInt4) + , Column PGInt4 + , Column PGInt4 + , Column PGInt4 + , Column PGText + ,(Column PGTimestamptz) + , Column PGJsonb + ) + +nodeTable' = Table "nodes" (PP.p7 ( optional "id" + , required "typename" + , required "user_id" + , required "parent_id" + , required "name" + , optional "date" + , required "hyperdata" + ) + ) + + queryNodeTable :: Query NodeRead queryNodeTable = queryTable nodeTable -selectNodes :: Column PGInt4 -> Query NodeRead -selectNodes id = proc () -> do +selectNode :: Column PGInt4 -> Query NodeRead +selectNode id = proc () -> do row <- queryNodeTable -< () restrict -< node_id row .== id returnA -< row @@ -142,13 +176,11 @@ selectNodesWith' parentId maybeNodeType = proc () -> do deleteNode :: Connection -> Int -> IO Int -deleteNode conn n = fromIntegral - <$> runDelete conn nodeTable +deleteNode conn n = fromIntegral <$> runDelete conn nodeTable (\(Node n_id _ _ _ _ _ _) -> n_id .== pgInt4 n) deleteNodes :: Connection -> [Int] -> IO Int -deleteNodes conn ns = fromIntegral - <$> runDelete conn nodeTable +deleteNodes conn ns = fromIntegral <$> runDelete conn nodeTable (\(Node n_id _ _ _ _ _ _) -> in_ ((map pgInt4 ns)) n_id) @@ -164,6 +196,10 @@ getNodesWithParentId :: Connection -> Int -> Maybe Text -> IO [Node HyperdataDocument] getNodesWithParentId conn n _ = runQuery conn $ selectNodesWithParentID n +getNodesWithParentId' :: Connection -> Int + -> Maybe Text -> IO [Node Value] +getNodesWithParentId' conn n _ = runQuery conn $ selectNodesWithParentID n + selectNodesWithParentID :: Int -> Query NodeRead selectNodesWithParentID n = proc () -> do @@ -182,12 +218,40 @@ selectNodesWithType type_id = proc () -> do restrict -< tn .== type_id returnA -< row +getNode' :: Connection -> Int -> IO (Node Value) +getNode' c id = do + fromMaybe (error "TODO: 404") . headMay <$> runQuery c (limit 1 $ selectNode (pgInt4 id)) + + getNode :: Connection -> Int -> IO (Node HyperdataDocument) getNode conn id = do - fromMaybe (error "TODO: 404") . headMay <$> runQuery conn (limit 1 $ selectNodes (pgInt4 id)) + fromMaybe (error "TODO: 404") . headMay <$> runQuery conn (limit 1 $ selectNode (pgInt4 id)) getNodesWithType :: Connection -> Column PGInt4 -> IO [Node HyperdataDocument] getNodesWithType conn type_id = do runQuery conn $ selectNodesWithType type_id - +type UserId = NodeId +type NodeWrite' = NodePoly (Maybe Int) Int Int (ParentId) Text (Maybe UTCTime) ByteString +type TypeId = Int + +--node :: UserId -> ParentId -> NodeType -> Text -> Value -> NodeWrite' +node :: UserId -> ParentId -> NodeType -> Text -> ByteString -> NodeWrite' +node userId parentId nodeType name nodeData = Node Nothing typeId userId parentId name Nothing byteData + where + typeId = nodeTypeId nodeType + byteData = nodeData + --byteData = encode nodeData + +node2write pid (Node id tn ud _ nm dt hp) = ((pgInt4 <$> id) + ,(pgInt4 tn) + ,(pgInt4 ud) + ,(pgInt4 pid) + ,(pgStrictText nm) + ,(pgUTCTime <$> dt) + ,(pgStrictJSONB hp) + ) + + +mkNode :: Connection -> ParentId -> [NodeWrite'] -> IO Int64 +mkNode conn pid ns = runInsertMany conn nodeTable' $ map (node2write pid) ns diff --git a/src/Gargantext/Prelude.hs b/src/Gargantext/Prelude.hs index a0afb7ec..8f973181 100644 --- a/src/Gargantext/Prelude.hs +++ b/src/Gargantext/Prelude.hs @@ -19,7 +19,7 @@ commentary with @some markup@. module Gargantext.Prelude ( module Gargantext.Prelude , module Protolude - , headMay + , headMay, lastMay , module Text.Show , module Text.Read , cs @@ -31,7 +31,7 @@ module Gargantext.Prelude import GHC.Exts (sortWith) import Data.Maybe (isJust, fromJust, maybe) -import Protolude ( Bool(True, False), Int, Double, Integer +import Protolude ( Bool(True, False), Int, Int64, Double, Integer , Fractional, Num, Maybe(Just,Nothing) , Enum, Bounded, Float , Floating, Char, IO @@ -67,7 +67,7 @@ import qualified Data.Map as M import Data.Map.Strict (insertWith) import qualified Data.Vector as V -import Safe (headMay) +import Safe (headMay, lastMay) import Text.Show (Show(), show) import Text.Read (Read()) import Data.String.Conversions (cs) -- 2.21.0