@@ -7,15 +7,20 @@ module ProjectM36.Client
77 DatabaseName,
88 ConnectionError,
99 connectProjectM36,
10−-- disconnectedTransaction,
11−-- transactionGraph,
1210 close,
1311 executeRelationalExpr,
1412 executeDatabaseContextExpr,
1513 executeGraphExpr,
1614 commit,
1715 rollback,
16+ typeForRelationalExpr,
17+ inclusionDependencies,
18+ planForDatabaseContextExpr,
19+ attributesForRelationalExpr,
1820 processPersistence,
21+ transactionGraphAsRelation,
22+ headName,
23+ headTransactionUUID,
1924 PersistenceStrategy(..),
2025 RelationalExpr(..),
2126 DatabaseExpr(..),
@@ -25,11 +30,14 @@ module ProjectM36.Client
2530 Atomable,
2631 Atom(..),
2732 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
2935import ProjectM36.Error
36+import ProjectM36.Relation
37+import ProjectM36.StaticOptimizer
3038import Control.Monad.State
3139import ProjectM36.Transaction
32−import ProjectM36.RelationalExpression
40+import qualified ProjectM36.RelationalExpression as RE
3341import ProjectM36.TransactionGraph
3442import ProjectM36.TransactionGraph.Persist
3543import ProjectM36.Attribute
@@ -41,12 +49,14 @@ import Control.Distributed.Process.Extras.Internal.Types (whereisRemote)
4149import Control.Distributed.Process.ManagedProcess.Client (call)
4250import Control.Distributed.Process (NodeId(..))
4351
52+import Data.UUID (UUID)
4453import Data.UUID.V4 (nextRandom)
4554import Control.Concurrent.STM
4655import Data.Word
4756import Control.Distributed.Process (ProcessId)
4857import Control.Exception (IOException)
4958import Control.Concurrent.MVar
59+import qualified Data.Map as M
5060
5161type Hostname = StringType
5262
@@ -81,7 +91,7 @@ connectProjectM36 :: ConnectionInfo -> IO (Either ConnectionError Connection)
8191--create a new in-memory database/transaction graph
8292connectProjectM36 (InProcessConnectionInfo strat) = do
8393 freshUUID <- nextRandom
84− let bootstrapContext = basicDatabaseContext
94+ let bootstrapContext = RE.basicDatabaseContext
8595 freshDiscon = newDisconnectedTransaction freshUUID bootstrapContext
8696 freshGraph = bootstrapTransactionGraph freshUUID bootstrapContext
8797 case strat of
@@ -129,15 +139,6 @@ connectPersistentProjectM36 strat sync dbdir freshDiscon freshGraph = do
129139 tvar <- newTVarIO (freshDiscon, graph')
130140 return $ Right $ InProcessConnection strat tvar
131141
132−{-
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)
136−
137−transactionGraph :: Connection -> IO (TransactionGraph)
138−transactionGraph (InProcessConnection _ tvar) = liftM snd (readTVarIO tvar)
139−-}
140−
141142close :: Connection -> IO ()
142143close (InProcessConnection _ _) = pure ()
143144close (RemoteProcessConnection serverProcessId) = do
@@ -152,12 +153,12 @@ close (RemoteProcessConnection serverProcessId) = do
152153executeRelationalExpr :: Connection -> RelationalExpr -> IO (Either RelationalError Relation)
153154executeRelationalExpr (InProcessConnection _ tvar) expr = atomically $ do
154155 ((DisconnectedTransaction _ context), _) <- readTVar tvar
155− return $ evalState (evalRelationalExpr expr) context
156+ return $ evalState (RE.evalRelationalExpr expr) context
156157
157158executeDatabaseContextExpr :: Connection -> DatabaseExpr -> IO (Maybe RelationalError)
158159executeDatabaseContextExpr (InProcessConnection _ tvar) expr = atomically $ do
159160 ((DisconnectedTransaction parentUUID context), graph) <- readTVar tvar
160− case runState (evalContextExpr expr) context of
161+ case runState (RE.evalContextExpr expr) context of
161162 (Just err,_) -> return $ Just err
162163 (Nothing, context') -> do
163164 let newDiscon = DisconnectedTransaction parentUUID context'
@@ -191,4 +192,56 @@ rollback conn = executeGraphExpr conn Rollback
191192processPersistence :: PersistenceStrategy -> TransactionGraph -> IO ()
192193processPersistence NoPersistence _ = return ()
193194processPersistence (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
196+
197+typeForRelationalExpr :: Connection -> RelationalExpr -> IO (Either RelationalError Relation)
198+typeForRelationalExpr conn@(InProcessConnection _ _) relExpr = atomically $ typeForRelationalExprSTM conn relExpr
199+
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
204+
205+inclusionDependencies :: Connection -> IO (M.Map IncDepName InclusionDependency)
206+inclusionDependencies (InProcessConnection _ tvar) = do
207+ atomically $ do
208+ ((DisconnectedTransaction _ context), _) <- readTVar tvar
209+ pure (B.inclusionDependencies context)
210+
211+planForDatabaseContextExpr :: Connection -> DatabaseExpr -> IO (Either RelationalError DatabaseExpr)
212+planForDatabaseContextExpr (InProcessConnection _ tvar) dbExpr = do
213+ atomically $ do
214+ ((DisconnectedTransaction _ context), _) <- readTVar tvar
215+ pure $ evalState (applyStaticDatabaseOptimization dbExpr) context
216+
217+transactionGraphAsRelation :: Connection -> IO (Either RelationalError Relation)
218+transactionGraphAsRelation (InProcessConnection _ tvar) = do
219+ atomically $ do
220+ (discon, graph) <- readTVar tvar
221+ pure $ graphAsRelation discon graph
222+
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
229+
230+-- | Returns the UUID for the connection's disconnected transaction committed parent transaction.
231+headTransactionUUID :: Connection -> IO (UUID)
232+headTransactionUUID (InProcessConnection _ tvar) = do
233+ atomically $ do
234+ (DisconnectedTransaction parentUUID _, _) <- readTVar tvar
235+ pure parentUUID
236+
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
240+ atomically $ do
241+ (DisconnectedTransaction parentUUID _, graph) <- readTVar tvar
242+ pure $ case transactionForUUID parentUUID graph of
243+ Left _ -> Nothing
244+ Right parentTrans -> headNameForTransaction parentTrans graph
245+
246+
247+