@@ -7,15 +7,20 @@ module ProjectM36.Client
7 DatabaseName,
7 DatabaseName,
8 ConnectionError,
8 ConnectionError,
9 connectProjectM36,
9 connectProjectM36,
10−-- disconnectedTransaction,
13 executeRelationalExpr,
11 executeRelationalExpr,
14 executeDatabaseContextExpr,
12 executeDatabaseContextExpr,
15 executeGraphExpr,
13 executeGraphExpr,
16+ typeForRelationalExpr,
17+ inclusionDependencies,
18+ planForDatabaseContextExpr,
19+ attributesForRelationalExpr,
18 processPersistence,
20 processPersistence,
21+ transactionGraphAsRelation,
19 PersistenceStrategy(..),
24 PersistenceStrategy(..),
20 RelationalExpr(..),
25 RelationalExpr(..),
21 DatabaseExpr(..),
26 DatabaseExpr(..),
@@ -25,11 +30,14 @@ module ProjectM36.Client
27 AtomType(..)) where
32 AtomType(..)) where
28−import ProjectM36.Base
33+import ProjectM36.Base hiding (inclusionDependencies) --defined in this module as well
34+import qualified ProjectM36.Base as B
29import ProjectM36.Error
35import ProjectM36.Error
36+import ProjectM36.Relation
37+import ProjectM36.StaticOptimizer
30import Control.Monad.State
38import Control.Monad.State
31import ProjectM36.Transaction
39import ProjectM36.Transaction
32−import ProjectM36.RelationalExpression
40+import qualified ProjectM36.RelationalExpression as RE
33import ProjectM36.TransactionGraph
41import ProjectM36.TransactionGraph
34import ProjectM36.TransactionGraph.Persist
42import ProjectM36.TransactionGraph.Persist
35import ProjectM36.Attribute
43import ProjectM36.Attribute
@@ -41,12 +49,14 @@ import Control.Distributed.Process.Extras.Internal.Types (whereisRemote)
41import Control.Distributed.Process.ManagedProcess.Client (call)
49import Control.Distributed.Process.ManagedProcess.Client (call)
42import Control.Distributed.Process (NodeId(..))
50import Control.Distributed.Process (NodeId(..))
52+import Data.UUID (UUID)
44import Data.UUID.V4 (nextRandom)
53import Data.UUID.V4 (nextRandom)
45import Control.Concurrent.STM
54import Control.Concurrent.STM
46import Data.Word
55import Data.Word
47import Control.Distributed.Process (ProcessId)
56import Control.Distributed.Process (ProcessId)
48import Control.Exception (IOException)
57import Control.Exception (IOException)
49import Control.Concurrent.MVar
58import Control.Concurrent.MVar
59+import qualified Data.Map as M
51type Hostname = StringType
61type Hostname = StringType
@@ -81,7 +91,7 @@ connectProjectM36 :: ConnectionInfo -> IO (Either ConnectionError Connection)
81--create a new in-memory database/transaction graph
91--create a new in-memory database/transaction graph
82connectProjectM36 (InProcessConnectionInfo strat) = do
92connectProjectM36 (InProcessConnectionInfo strat) = do
83 freshUUID <- nextRandom
93 freshUUID <- nextRandom
84− let bootstrapContext = basicDatabaseContext
94+ let bootstrapContext = RE.basicDatabaseContext
85 freshDiscon = newDisconnectedTransaction freshUUID bootstrapContext
95 freshDiscon = newDisconnectedTransaction freshUUID bootstrapContext
86 freshGraph = bootstrapTransactionGraph freshUUID bootstrapContext
96 freshGraph = bootstrapTransactionGraph freshUUID bootstrapContext
87 case strat of
97 case strat of
@@ -129,15 +139,6 @@ connectPersistentProjectM36 strat sync dbdir freshDiscon freshGraph = do
129 tvar <- newTVarIO (freshDiscon, graph')
139 tvar <- newTVarIO (freshDiscon, graph')
130 return $ Right $ InProcessConnection strat tvar
140 return $ Right $ InProcessConnection strat tvar
133−-- if these are operated remotely, they are too expensive- keep the working space (discon) on the server
134−disconnectedTransaction :: Connection -> IO (DisconnectedTransaction)
135−disconnectedTransaction (InProcessConnection _ tvar) = liftM fst (readTVarIO tvar)
137−transactionGraph :: Connection -> IO (TransactionGraph)
138−transactionGraph (InProcessConnection _ tvar) = liftM snd (readTVarIO tvar)
141close :: Connection -> IO ()
142close :: Connection -> IO ()
142close (InProcessConnection _ _) = pure ()
143close (InProcessConnection _ _) = pure ()
143close (RemoteProcessConnection serverProcessId) = do
144close (RemoteProcessConnection serverProcessId) = do
@@ -152,12 +153,12 @@ close (RemoteProcessConnection serverProcessId) = do
152executeRelationalExpr :: Connection -> RelationalExpr -> IO (Either RelationalError Relation)
153executeRelationalExpr :: Connection -> RelationalExpr -> IO (Either RelationalError Relation)
153executeRelationalExpr (InProcessConnection _ tvar) expr = atomically $ do
154executeRelationalExpr (InProcessConnection _ tvar) expr = atomically $ do
154 ((DisconnectedTransaction _ context), _) <- readTVar tvar
155 ((DisconnectedTransaction _ context), _) <- readTVar tvar
155− return $ evalState (evalRelationalExpr expr) context
156+ return $ evalState (RE.evalRelationalExpr expr) context
157executeDatabaseContextExpr :: Connection -> DatabaseExpr -> IO (Maybe RelationalError)
158executeDatabaseContextExpr :: Connection -> DatabaseExpr -> IO (Maybe RelationalError)
158executeDatabaseContextExpr (InProcessConnection _ tvar) expr = atomically $ do
159executeDatabaseContextExpr (InProcessConnection _ tvar) expr = atomically $ do
159 ((DisconnectedTransaction parentUUID context), graph) <- readTVar tvar
160 ((DisconnectedTransaction parentUUID context), graph) <- readTVar tvar
160− case runState (evalContextExpr expr) context of
161+ case runState (RE.evalContextExpr expr) context of
161 (Just err,_) -> return $ Just err
162 (Just err,_) -> return $ Just err
162 (Nothing, context') -> do
163 (Nothing, context') -> do
163 let newDiscon = DisconnectedTransaction parentUUID context'
164 let newDiscon = DisconnectedTransaction parentUUID context'
@@ -191,4 +192,56 @@ rollback conn = executeGraphExpr conn Rollback
191processPersistence :: PersistenceStrategy -> TransactionGraph -> IO ()
192processPersistence :: PersistenceStrategy -> TransactionGraph -> IO ()
192processPersistence NoPersistence _ = return ()
193processPersistence NoPersistence _ = return ()
193processPersistence (MinimalPersistence dbdir) graph = transactionGraphPersist NoDiskSync dbdir graph
194processPersistence (MinimalPersistence dbdir) graph = transactionGraphPersist NoDiskSync dbdir graph
194−processPersistence (CrashSafePersistence dbdir) graph = transactionGraphPersist FsyncDiskSync dbdir graph
195+processPersistence (CrashSafePersistence dbdir) graph = transactionGraphPersist FsyncDiskSync dbdir graph
197+typeForRelationalExpr :: Connection -> RelationalExpr -> IO (Either RelationalError Relation)
198+typeForRelationalExpr conn@(InProcessConnection _ _) relExpr = atomically $ typeForRelationalExprSTM conn relExpr
200+typeForRelationalExprSTM :: Connection -> RelationalExpr -> STM (Either RelationalError Relation)
201+typeForRelationalExprSTM (InProcessConnection _ tvar) relExpr = do
202+ (DisconnectedTransaction _ context, _) <- readTVar tvar
203+ pure $ evalState (RE.typeForRelationalExpr relExpr) context
205+inclusionDependencies :: Connection -> IO (M.Map IncDepName InclusionDependency)
206+inclusionDependencies (InProcessConnection _ tvar) = do
208+ ((DisconnectedTransaction _ context), _) <- readTVar tvar
209+ pure (B.inclusionDependencies context)
211+planForDatabaseContextExpr :: Connection -> DatabaseExpr -> IO (Either RelationalError DatabaseExpr)
212+planForDatabaseContextExpr (InProcessConnection _ tvar) dbExpr = do
214+ ((DisconnectedTransaction _ context), _) <- readTVar tvar
215+ pure $ evalState (applyStaticDatabaseOptimization dbExpr) context
217+transactionGraphAsRelation :: Connection -> IO (Either RelationalError Relation)
218+transactionGraphAsRelation (InProcessConnection _ tvar) = do
220+ (discon, graph) <- readTVar tvar
221+ pure $ graphAsRelation discon graph
223+attributesForRelationalExpr :: Connection -> RelationalExpr -> IO (Either RelationalError Attributes)
224+attributesForRelationalExpr conn relExpr = atomically $ do
225+ eRelType <- typeForRelationalExprSTM conn relExpr
226+ pure $ case eRelType of
227+ Left err -> Left err
228+ Right relType -> Right $ attributes relType
230+-- | Returns the UUID for the connection's disconnected transaction committed parent transaction.
231+headTransactionUUID :: Connection -> IO (UUID)
232+headTransactionUUID (InProcessConnection _ tvar) = do
234+ (DisconnectedTransaction parentUUID _, _) <- readTVar tvar
237+-- | Returns Just the name of the head of the current disconnected transaction or Nothing.
238+headName :: Connection -> IO (Maybe HeadName)
239+headName (InProcessConnection _ tvar) = do
241+ (DisconnectedTransaction parentUUID _, graph) <- readTVar tvar
242+ pure $ case transactionForUUID parentUUID graph of
244+ Right parentTrans -> headNameForTransaction parentTrans graph