on master help sign in
add some haddock lines in the main modules of concern.
b3f3f02AgentM
Database/Persist/ProjectM36.hs+1−1
@@ -346,7 +346,7 @@ instance FromJSON C.ConnectionInfo where
346 return ctype
346 return ctype
347
347
348instance PersistConfig C.ConnectionInfo where
348instance PersistConfig C.ConnectionInfo where
349− -- | Hold onto a connection as well a default session.
349+ --- | Hold onto a connection as well a default session.
350 type PersistConfigBackend C.ConnectionInfo = ReaderT ProjectM36Backend
350 type PersistConfigBackend C.ConnectionInfo = ReaderT ProjectM36Backend
351 type PersistConfigPool C.ConnectionInfo = ProjectM36Backend
351 type PersistConfigPool C.ConnectionInfo = ProjectM36Backend
352
352
ProjectM36/Base.hs+39−14
@@ -26,6 +26,7 @@ import ProjectM36.ConcreteTypeRep
26
26
27type StringType = Text
27type StringType = Text
28
28
29+-- | Any data type represents as an 'Atom' in the database must adhere to the 'Atomable' typeclass.
29class (Read a,
30class (Read a,
30 Hashable a,
31 Hashable a,
31 Binary a,
32 Binary a,
@@ -54,6 +55,7 @@ instance Atomable Bool
54instance Atomable Relation
55instance Atomable Relation
55instance (Atomable a) => Atomable (Maybe a)
56instance (Atomable a) => Atomable (Maybe a)
56
57
58+-- | Database atoms are the smallest, undecomposable units of a tuple. Common examples are integers, text, or unique identity keys.
57data Atom = forall a. Atomable a => Atom a
59data Atom = forall a. Atomable a => Atom a
58
60
59instance Eq Atom where
61instance Eq Atom where
@@ -94,6 +96,7 @@ instance NFData Atom where
94instance Hashable Atom where
96instance Hashable Atom where
95 hashWithSalt salt (Atom a) = hashWithSalt salt a
97 hashWithSalt salt (Atom a) = hashWithSalt salt a
96
98
99+-- | Return the type of an 'Atom'.
97atomTypeForAtom :: Atom -> AtomType
100atomTypeForAtom :: Atom -> AtomType
98atomTypeForAtom (Atom atom) = case cast atom of
101atomTypeForAtom (Atom atom) = case cast atom of
99 Just (Relation attrs _) -> RelationAtomType attrs
102 Just (Relation attrs _) -> RelationAtomType attrs
@@ -116,12 +119,14 @@ data AtomType = AtomType ConcreteTypeRep |
116 AnyAtomType --wildcard used in Atom Functions
119 AnyAtomType --wildcard used in Atom Functions
117 deriving (Eq,NFData,Generic,Binary,Show)
120 deriving (Eq,NFData,Generic,Binary,Show)
118
121
122+-- | Return True iff the atom type argument is relation-valued. If True, this indicates that the Atom contains a relation.
119isRelationAtomType :: AtomType -> Bool
123isRelationAtomType :: AtomType -> Bool
120isRelationAtomType (RelationAtomType _) = True
124isRelationAtomType (RelationAtomType _) = True
121isRelationAtomType _ = False
125isRelationAtomType _ = False
122
126
123type AttributeName = StringType
127type AttributeName = StringType
124
128
129+-- | A relation's type is composed of attribute names and types.
125data Attribute = Attribute AttributeName AtomType deriving (Eq, Show, Generic)
130data Attribute = Attribute AttributeName AtomType deriving (Eq, Show, Generic)
126
131
127instance Hashable Attribute where
132instance Hashable Attribute where
@@ -131,8 +136,10 @@ instance NFData Attribute where rnf = genericRnf
131
136
132instance Binary Attribute
137instance Binary Attribute
133
138
139+-- | 'Attributes' represent the head of a relation.
134type Attributes = V.Vector Attribute
140type Attributes = V.Vector Attribute
135
141
142+-- | Equality function for a set of attributes.
136attributesEqual :: Attributes -> Attributes -> Bool
143attributesEqual :: Attributes -> Attributes -> Bool
137attributesEqual attrs1 attrs2 = attrsAsSet attrs1 == attrsAsSet attrs2
144attributesEqual attrs1 attrs2 = attrsAsSet attrs1 == attrsAsSet attrs2
138 where
145 where
@@ -141,6 +148,7 @@ attributesEqual attrs1 attrs2 = attrsAsSet attrs1 == attrsAsSet attrs2
141sortedAttributesIndices :: Attributes -> [(Int, Attribute)]
148sortedAttributesIndices :: Attributes -> [(Int, Attribute)]
142sortedAttributesIndices attrs = L.sortBy (\(_, (Attribute name1 _)) (_,(Attribute name2 _)) -> compare name1 name2) $ V.toList (V.indexed attrs)
149sortedAttributesIndices attrs = L.sortBy (\(_, (Attribute name1 _)) (_,(Attribute name2 _)) -> compare name1 name2) $ V.toList (V.indexed attrs)
143
150
151+-- | The relation's tuple set is the body of the relation.
144newtype RelationTupleSet = RelationTupleSet { asList :: [RelationTuple] } deriving (Hashable, Show, Generic, Binary)
152newtype RelationTupleSet = RelationTupleSet { asList :: [RelationTuple] } deriving (Hashable, Show, Generic, Binary)
145
153
146instance Read Relation where
154instance Read Relation where
@@ -168,7 +176,7 @@ instance Hashable RelationTuple where
168 sortedAttrs = map snd sortedAttrsIndices
176 sortedAttrs = map snd sortedAttrsIndices
169 sortedTupVec = V.map (\(index, _) -> tupVec V.! index) $ V.fromList sortedAttrsIndices
177 sortedTupVec = V.map (\(index, _) -> tupVec V.! index) $ V.fromList sortedAttrsIndices
170
178
171−--maybe the attribute->int mapping should be stored once in the relation and then passed down when needed
179+-- | A tuple is a set of attributes mapped to their 'Atom' values.
172data RelationTuple = RelationTuple Attributes (V.Vector Atom) deriving (Show, Generic)
180data RelationTuple = RelationTuple Attributes (V.Vector Atom) deriving (Show, Generic)
173
181
174instance Binary RelationTuple
182instance Binary RelationTuple
@@ -202,22 +210,35 @@ instance Binary Relation
202data RelationCardinality = Uncountable | Countable Int deriving (Eq, Show, Generic, Ord)
210data RelationCardinality = Uncountable | Countable Int deriving (Eq, Show, Generic, Ord)
203data RelationSizeInfinite = RelationSizeInfinite
211data RelationSizeInfinite = RelationSizeInfinite
204
212
213+-- | Relation variables are identified by their names.
205type RelVarName = StringType
214type RelVarName = StringType
206
215
216+-- | A relational expression represents query (read) operations on a database.
207data RelationalExpr where
217data RelationalExpr where
218+ --- | Create and reference a relation from attributes and a tuple set.
208 MakeStaticRelation :: Attributes -> RelationTupleSet -> RelationalExpr
219 MakeStaticRelation :: Attributes -> RelationTupleSet -> RelationalExpr
220+ --- | Reference an existing relation in Haskell-space.
209 ExistingRelation :: Relation -> RelationalExpr
221 ExistingRelation :: Relation -> RelationalExpr
210 --MakeFunctionalRelation (creates a relation from a tuple-generating function, potentially infinite)
222 --MakeFunctionalRelation (creates a relation from a tuple-generating function, potentially infinite)
211 --in Tutorial D, relational variables pick up the type of the first relation assigned to them
223 --in Tutorial D, relational variables pick up the type of the first relation assigned to them
212 --relational variables should also be able to be explicitly-typed like in Haskell
224 --relational variables should also be able to be explicitly-typed like in Haskell
225+ --- | Reference a relation variable by its name.
213 RelationVariable :: RelVarName -> RelationalExpr
226 RelationVariable :: RelVarName -> RelationalExpr
227+ --- | Create a projection over attribute names. (Note that the 'AttributeNames' structure allows for the names to be inverted.)
214 Project :: AttributeNames -> RelationalExpr -> RelationalExpr
228 Project :: AttributeNames -> RelationalExpr -> RelationalExpr
229+ --- | Create a union of two relational expressions. The expressions should have identical attributes.
215 Union :: RelationalExpr -> RelationalExpr -> RelationalExpr
230 Union :: RelationalExpr -> RelationalExpr -> RelationalExpr
231+ --- | Create a join of two relational expressions. The join occurs on attributes which are identical. If the expressions have no overlapping attributes, the join becomes a cross-product of both tuple sets.
216 Join :: RelationalExpr -> RelationalExpr -> RelationalExpr
232 Join :: RelationalExpr -> RelationalExpr -> RelationalExpr
233+ --- | Rename an attribute (first argument) to another (second argument).
217 Rename :: AttributeName -> AttributeName -> RelationalExpr -> RelationalExpr
234 Rename :: AttributeName -> AttributeName -> RelationalExpr -> RelationalExpr
235+ --- | Create a sub-relation composed of the first argument's attributes which will become an attribute of the result expression. The unreferenced attributes are not altered in the result but duplicate tuples in the projection of the expression minus the attribute names are compressed into one. For more information, <https://github.com/agentm/project-m36/blob/master/docs/introduction_to_the_relational_algebra.markdown#group read the relational algebra tutorial.>
218 Group :: AttributeNames -> AttributeName -> RelationalExpr -> RelationalExpr
236 Group :: AttributeNames -> AttributeName -> RelationalExpr -> RelationalExpr
237+ --- | Create an expression to unwrap a sub-relation contained within at an attribute's name. Note that this is not always an inverse of a group operation.
219 Ungroup :: AttributeName -> RelationalExpr -> RelationalExpr
238 Ungroup :: AttributeName -> RelationalExpr -> RelationalExpr
239+ --- | Filter the tuples of the relational expression to only retain the tuples which evaluate against the restriction predicate to true.
220 Restrict :: RestrictionPredicateExpr -> RelationalExpr -> RelationalExpr
240 Restrict :: RestrictionPredicateExpr -> RelationalExpr -> RelationalExpr
241+ --- | Returns the true relation iff
221 Equals :: RelationalExpr -> RelationalExpr -> RelationalExpr
242 Equals :: RelationalExpr -> RelationalExpr -> RelationalExpr
222 NotEquals :: RelationalExpr -> RelationalExpr -> RelationalExpr
243 NotEquals :: RelationalExpr -> RelationalExpr -> RelationalExpr
223 Extend :: TupleExpr -> RelationalExpr -> RelationalExpr
244 Extend :: TupleExpr -> RelationalExpr -> RelationalExpr
@@ -226,21 +247,21 @@ data RelationalExpr where
226
247
227instance Binary RelationalExpr
248instance Binary RelationalExpr
228
249
250+-- | The DatabaseContext is a snapshot of a database's evolving state and contains everything a database client can change over time.
229data DatabaseContext = DatabaseContext {
251data DatabaseContext = DatabaseContext {
230 inclusionDependencies :: M.Map IncDepName InclusionDependency,
252 inclusionDependencies :: M.Map IncDepName InclusionDependency,
231 relationVariables :: M.Map RelVarName Relation,
253 relationVariables :: M.Map RelVarName Relation,
232 atomFunctions :: AtomFunctions
254 atomFunctions :: AtomFunctions
233 } deriving (Show, Generic)
255 } deriving (Show, Generic)
234
256
235−--instance Binary DatabaseContext
236−
237type IncDepName = StringType
257type IncDepName = StringType
238
258
259+-- | Inclusion dependencies represent every possible database constraints. Constraints enforce specific, arbitrarily-complex rules to which the database context must adhere.
239data InclusionDependency = InclusionDependency RelationalExpr RelationalExpr deriving (Show, Eq, Generic)
260data InclusionDependency = InclusionDependency RelationalExpr RelationalExpr deriving (Show, Eq, Generic)
240
261
241instance Binary InclusionDependency
262instance Binary InclusionDependency
242
263
243−--Database context expressions modify the database context while relational expressions do not
264+-- | Database context expressions modify the database context.
244data DatabaseExpr where
265data DatabaseExpr where
245 Define :: RelVarName -> Attributes -> DatabaseExpr
266 Define :: RelVarName -> Attributes -> DatabaseExpr
246 Undefine :: RelVarName -> DatabaseExpr --forget existence of relvar X
267 Undefine :: RelVarName -> DatabaseExpr --forget existence of relvar X
@@ -255,6 +276,7 @@ data DatabaseExpr where
255
276
256type DatabaseState a = State DatabaseContext a
277type DatabaseState a = State DatabaseContext a
257
278
279+-- | Restriction predicate are boolean algebra components which, when composed, indicate whether or not a tuple should be retained during a restriction (filtering) operation.
258data RestrictionPredicateExpr where
280data RestrictionPredicateExpr where
259 TruePredicate :: RestrictionPredicateExpr
281 TruePredicate :: RestrictionPredicateExpr
260 AndPredicate :: RestrictionPredicateExpr -> RestrictionPredicateExpr -> RestrictionPredicateExpr
282 AndPredicate :: RestrictionPredicateExpr -> RestrictionPredicateExpr -> RestrictionPredicateExpr
@@ -268,11 +290,12 @@ data RestrictionPredicateExpr where
268instance Binary RestrictionPredicateExpr
290instance Binary RestrictionPredicateExpr
269
291
270-- child + parent links
292-- child + parent links
271−-- the string represents the branch name and can be used to find the named HEADs
293+-- | A transaction graph's head name references the leaves of the transaction graph and can be used during session creation to indicate at which point in the graph commits should persist.
272type HeadName = StringType
294type HeadName = StringType
273
295
274type TransactionHeads = M.Map HeadName Transaction
296type TransactionHeads = M.Map HeadName Transaction
275
297
298+-- | The transaction graph is the global database's state which references every committed transaction.
276data TransactionGraph = TransactionGraph TransactionHeads (S.Set Transaction)
299data TransactionGraph = TransactionGraph TransactionHeads (S.Set Transaction)
277 deriving (Show, Eq)
300 deriving (Show, Eq)
278
301
@@ -282,20 +305,20 @@ transactionsForGraph (TransactionGraph _ t) = t
282transactionHeadsForGraph :: TransactionGraph -> TransactionHeads
305transactionHeadsForGraph :: TransactionGraph -> TransactionHeads
283transactionHeadsForGraph (TransactionGraph heads _) = heads
306transactionHeadsForGraph (TransactionGraph heads _) = heads
284
307
308+-- | Every transaction has context-specific information attached to it.
285data TransactionInfo = TransactionInfo UUID (S.Set UUID) | -- 1 parent + n children
309data TransactionInfo = TransactionInfo UUID (S.Set UUID) | -- 1 parent + n children
286 MergeTransactionInfo UUID UUID (S.Set UUID) -- 2 parents, n children
310 MergeTransactionInfo UUID UUID (S.Set UUID) -- 2 parents, n children
287 deriving(Show, Generic)
311 deriving(Show, Generic)
288
312
289instance Binary TransactionInfo
313instance Binary TransactionInfo
290
314
315+-- | Every set of modifications made to the database are atomically committed to the transaction graph as a transaction.
291data Transaction = Transaction UUID TransactionInfo DatabaseContext -- self uuid
316data Transaction = Transaction UUID TransactionInfo DatabaseContext -- self uuid
292 deriving (Show, Generic)
317 deriving (Show, Generic)
293
318
294--instance Binary Transaction
319--instance Binary Transaction
295
320
296−--represents an "in-progress" transaction which has not yet been added to the transaction graph
321+-- | The disconnected transaction represents an in-progress workspace used by sessions before changes are committed. This is similar to git's "index". After a transaction is committed, it is "connected" in the transaction graph and can no longer be modified.
297−--one the transaction is "complete", it is committed and no longer can be changed
298−-- this is similar to the index in git
299data DisconnectedTransaction = DisconnectedTransaction UUID DatabaseContext --parentUUID, context
322data DisconnectedTransaction = DisconnectedTransaction UUID DatabaseContext --parentUUID, context
300
323
301transactionUUID :: Transaction -> UUID
324transactionUUID :: Transaction -> UUID
@@ -313,7 +336,7 @@ instance Eq Transaction where
313instance Ord Transaction where
336instance Ord Transaction where
314 compare (Transaction uuidA _ _) (Transaction uuidB _ _) = compare uuidA uuidB
337 compare (Transaction uuidA _ _) (Transaction uuidB _ _) = compare uuidA uuidB
315
338
316−--used on the right side of attribute assignments
339+-- | An atom expression represents an action to take when extending a relation.
317data AtomExpr = AttributeAtomExpr AttributeName |
340data AtomExpr = AttributeAtomExpr AttributeName |
318 NakedAtomExpr Atom |
341 NakedAtomExpr Atom |
319 FunctionAtomExpr AtomFunctionName [AtomExpr] |
342 FunctionAtomExpr AtomFunctionName [AtomExpr] |
@@ -322,7 +345,7 @@ data AtomExpr = AttributeAtomExpr AttributeName |
322
345
323instance Binary AtomExpr
346instance Binary AtomExpr
324
347
325−--used to extend a relation
348+-- | A tuple expression declares what action to take when extending a relation.
326data TupleExpr = AttributeTupleExpr AttributeName AtomExpr
349data TupleExpr = AttributeTupleExpr AttributeName AtomExpr
327 deriving (Show, Eq, Generic)
350 deriving (Show, Eq, Generic)
328
351
@@ -333,6 +356,7 @@ type AtomFunctions = HS.HashSet AtomFunction
333
356
334type AtomFunctionName = StringType
357type AtomFunctionName = StringType
335
358
359+-- | An AtomFunction has a name, a type, and a function body to execute when called.
336data AtomFunction = AtomFunction {
360data AtomFunction = AtomFunction {
337 atomFuncName :: AtomFunctionName,
361 atomFuncName :: AtomFunctionName,
338 atomFuncType :: [AtomType],
362 atomFuncType :: [AtomType],
@@ -350,16 +374,17 @@ instance Show AtomFunction where
350 where
374 where
351 showArgTypes = concat (L.intersperse "->" $ map show (atomFuncType aFunc))
375 showArgTypes = concat (L.intersperse "->" $ map show (atomFuncType aFunc))
352
376
377+-- | The 'AttributeNames' structure represents a set of attribute names or the same set of names but inverted in the context of a relational expression. For example, if a relational expression has attributes named "a", "b", and "c", the 'InvertedAttributeNames' of ("a","c") is ("b").
353data AttributeNames = AttributeNames (S.Set AttributeName) |
378data AttributeNames = AttributeNames (S.Set AttributeName) |
354 InvertedAttributeNames (S.Set AttributeName)
379 InvertedAttributeNames (S.Set AttributeName)
355 deriving (Eq, Show, Generic)
380 deriving (Eq, Show, Generic)
356
381
357instance Binary AttributeNames
382instance Binary AttributeNames
358
383
359−--used for global dbms configuration- per-transaction flag is elsewhere
384+-- | The persistence strategy is a global database option which represents how to persist the database in the filesystem, if at all.
360−data PersistenceStrategy = NoPersistence | --no filesystem persistence/memory-only database
385+data PersistenceStrategy = NoPersistence | -- ^ no filesystem persistence/memory-only database
361− MinimalPersistence FilePath | --fsync off
386+ MinimalPersistence FilePath | -- ^ fsync off, not crash-safe
362− CrashSafePersistence FilePath --full fsync- not yet implemented
387+ CrashSafePersistence FilePath -- ^ full fsync to disk (flushes kernel and physical drive buffers to ensure that the transaction is on non-volatile storage)
363 deriving (Show, Read)
388 deriving (Show, Read)
364
389
365
390
ProjectM36/Client.hs+19−4
@@ -97,10 +97,11 @@ defaultHeadName = "master"
97defaultRemoteConnectionInfo :: ConnectionInfo
97defaultRemoteConnectionInfo :: ConnectionInfo
98defaultRemoteConnectionInfo = RemoteProcessConnectionInfo defaultDatabaseName (createNodeId "127.0.0.1" defaultServerPort)
98defaultRemoteConnectionInfo = RemoteProcessConnectionInfo defaultDatabaseName (createNodeId "127.0.0.1" defaultServerPort)
99
99
100−
100+-- | The 'Connection' represents either local or remote access to a database. All operations flow through the connection.
101data Connection = InProcessConnection PersistenceStrategy Sessions (TVar TransactionGraph) |
101data Connection = InProcessConnection PersistenceStrategy Sessions (TVar TransactionGraph) |
102 RemoteProcessConnection LocalNode ProcessId
102 RemoteProcessConnection LocalNode ProcessId
103
103
104+-- | There are several reasons why a connection can fail.
104data ConnectionError = SetupDatabaseDirectoryError PersistenceError |
105data ConnectionError = SetupDatabaseDirectoryError PersistenceError |
105 IOExceptionError IOException |
106 IOExceptionError IOException |
106 NoSuchDatabaseByNameError DatabaseName |
107 NoSuchDatabaseByNameError DatabaseName |
@@ -110,6 +111,7 @@ data ConnectionError = SetupDatabaseDirectoryError PersistenceError |
110remoteDBLookupName :: DatabaseName -> String
111remoteDBLookupName :: DatabaseName -> String
111remoteDBLookupName = (++) "db-"
112remoteDBLookupName = (++) "db-"
112
113
114+
113commonLocalNode :: IO (Either ConnectionError LocalNode)
115commonLocalNode :: IO (Either ConnectionError LocalNode)
114commonLocalNode = do
116commonLocalNode = do
115 eLocalTransport <- createTransport "127.0.0.1" "0" defaultTCPParameters
117 eLocalTransport <- createTransport "127.0.0.1" "0" defaultTCPParameters
@@ -117,7 +119,7 @@ commonLocalNode = do
117 Left err -> pure (Left $ IOExceptionError err)
119 Left err -> pure (Left $ IOExceptionError err)
118 Right localTransport -> newLocalNode localTransport initRemoteTable >>= pure . Right
120 Right localTransport -> newLocalNode localTransport initRemoteTable >>= pure . Right
119
121
120−-- connect to an in-process database
122+-- | To create a 'Connection' to a remote or local database, create a connectionInfo and call 'connectProjectM36'.
121connectProjectM36 :: ConnectionInfo -> IO (Either ConnectionError Connection)
123connectProjectM36 :: ConnectionInfo -> IO (Either ConnectionError Connection)
122--create a new in-memory database/transaction graph
124--create a new in-memory database/transaction graph
123connectProjectM36 (InProcessConnectionInfo strat) = do
125connectProjectM36 (InProcessConnectionInfo strat) = do
@@ -195,6 +197,7 @@ createSessionAtCommit_ commitUUID newSessionId (InProcessConnection _ sessions g
195 pure $ Right newSessionId
197 pure $ Right newSessionId
196createSessionAtCommit_ _ _ (RemoteProcessConnection _ _) = error "createSessionAtCommit_ called on remote connection"
198createSessionAtCommit_ _ _ (RemoteProcessConnection _ _) = error "createSessionAtCommit_ called on remote connection"
197
199
200+-- | Call 'createSessionAtHead' with a transaction graph's head's name to create a new session pinned to that head. This function returns a 'SessionId' which can be used in other function calls to reference the point in the transaction graph.
198createSessionAtHead :: HeadName -> Connection -> IO (Either RelationalError SessionId)
201createSessionAtHead :: HeadName -> Connection -> IO (Either RelationalError SessionId)
199createSessionAtHead headn conn@(InProcessConnection _ _ tvar) = do
202createSessionAtHead headn conn@(InProcessConnection _ _ tvar) = do
200 newSessionId <- nextRandom
203 newSessionId <- nextRandom
@@ -211,7 +214,7 @@ closeSession sessionId (InProcessConnection _ sessions _) = do
211 atomically $ do
214 atomically $ do
212 STMMap.delete sessionId sessions
215 STMMap.delete sessionId sessions
213closeSession sessionId conn@(RemoteProcessConnection _ _) = remoteCall conn (CloseSession sessionId)
216closeSession sessionId conn@(RemoteProcessConnection _ _) = remoteCall conn (CloseSession sessionId)
214−
217+-- | 'close' cleans up the database access connection. Note that sessions persist even after the connection is closed.
215close :: Connection -> IO ()
218close :: Connection -> IO ()
216close (InProcessConnection _ sessions _) = atomically $ do
219close (InProcessConnection _ sessions _) = atomically $ do
217 traverse_ (\(k,_) -> STMMap.delete k sessions) (STMMap.stream sessions)
220 traverse_ (\(k,_) -> STMMap.delete k sessions) (STMMap.stream sessions)
@@ -241,6 +244,7 @@ sessionForSessionId sessionId sessions = do
241 maybeSession <- STMMap.lookup sessionId sessions
244 maybeSession <- STMMap.lookup sessionId sessions
242 pure $ maybe (Left $ NoSuchSession sessionId) Right maybeSession
245 pure $ maybe (Left $ NoSuchSession sessionId) Right maybeSession
243
246
247+-- | Execute a relational expression in the context of the session and connection. Relational expressions are queries and therefore cannot alter the database.
244executeRelationalExpr :: SessionId -> Connection -> RelationalExpr -> IO (Either RelationalError Relation)
248executeRelationalExpr :: SessionId -> Connection -> RelationalExpr -> IO (Either RelationalError Relation)
245executeRelationalExpr sessionId (InProcessConnection _ sessions _) expr = atomically $ do
249executeRelationalExpr sessionId (InProcessConnection _ sessions _) expr = atomically $ do
246 eSession <- sessionForSessionId sessionId sessions
250 eSession <- sessionForSessionId sessionId sessions
@@ -249,6 +253,7 @@ executeRelationalExpr sessionId (InProcessConnection _ sessions _) expr = atomic
249 Right (Session (DisconnectedTransaction _ context)) -> pure $ evalState (RE.evalRelationalExpr expr) context
253 Right (Session (DisconnectedTransaction _ context)) -> pure $ evalState (RE.evalRelationalExpr expr) context
250executeRelationalExpr sessionId conn@(RemoteProcessConnection _ _) relExpr = remoteCall conn (ExecuteRelationalExpr sessionId relExpr)
254executeRelationalExpr sessionId conn@(RemoteProcessConnection _ _) relExpr = remoteCall conn (ExecuteRelationalExpr sessionId relExpr)
251
255
256+-- | Execute a database context expression in the context of the session and connection. Database expressions modify the current session's disconnected transaction but cannot modify the transaction graph.
252executeDatabaseContextExpr :: SessionId -> Connection -> DatabaseExpr -> IO (Maybe RelationalError)
257executeDatabaseContextExpr :: SessionId -> Connection -> DatabaseExpr -> IO (Maybe RelationalError)
253executeDatabaseContextExpr sessionId (InProcessConnection _ sessions _) expr = atomically $ do
258executeDatabaseContextExpr sessionId (InProcessConnection _ sessions _) expr = atomically $ do
254 eSession <- sessionForSessionId sessionId sessions
259 eSession <- sessionForSessionId sessionId sessions
@@ -263,6 +268,7 @@ executeDatabaseContextExpr sessionId (InProcessConnection _ sessions _) expr = a
263 return Nothing
268 return Nothing
264executeDatabaseContextExpr sessionId conn@(RemoteProcessConnection _ _) dbExpr = remoteCall conn (ExecuteDatabaseContextExpr sessionId dbExpr)
269executeDatabaseContextExpr sessionId conn@(RemoteProcessConnection _ _) dbExpr = remoteCall conn (ExecuteDatabaseContextExpr sessionId dbExpr)
265
270
271+-- | Execute a transaction graph expression in the context of the session and connection. Transaction graph operators modify the transaction graph state.
266executeGraphExpr :: SessionId -> Connection -> TransactionGraphOperator -> IO (Maybe RelationalError)
272executeGraphExpr :: SessionId -> Connection -> TransactionGraphOperator -> IO (Maybe RelationalError)
267executeGraphExpr sessionId (InProcessConnection strat sessions graphTvar) graphExpr = do
273executeGraphExpr sessionId (InProcessConnection strat sessions graphTvar) graphExpr = do
268 freshUUID <- nextRandom
274 freshUUID <- nextRandom
@@ -287,10 +293,12 @@ executeGraphExpr sessionId (InProcessConnection strat sessions graphTvar) graphE
287 return Nothing
293 return Nothing
288executeGraphExpr sessionId conn@(RemoteProcessConnection _ _) graphExpr = remoteCall conn (ExecuteGraphExpr sessionId graphExpr)
294executeGraphExpr sessionId conn@(RemoteProcessConnection _ _) graphExpr = remoteCall conn (ExecuteGraphExpr sessionId graphExpr)
289
295
296+-- | After modifying a session, 'commit' the transaction to the transaction graph at the head which the session is referencing.
290commit :: SessionId -> Connection -> IO (Maybe RelationalError)
297commit :: SessionId -> Connection -> IO (Maybe RelationalError)
291commit sessionId conn@(InProcessConnection _ _ _) = executeGraphExpr sessionId conn Commit
298commit sessionId conn@(InProcessConnection _ _ _) = executeGraphExpr sessionId conn Commit
292commit sessionId conn@(RemoteProcessConnection _ _) = remoteCall conn (ExecuteGraphExpr sessionId Commit)
299commit sessionId conn@(RemoteProcessConnection _ _) = remoteCall conn (ExecuteGraphExpr sessionId Commit)
293
300
301+-- | Discard any changes made in the current session. This resets the disconnected transaction to reference the original database context of the parent transaction and is a very cheap operation.
294rollback :: SessionId -> Connection -> IO (Maybe RelationalError)
302rollback :: SessionId -> Connection -> IO (Maybe RelationalError)
295rollback sessionId conn@(InProcessConnection _ _ _) = executeGraphExpr sessionId conn Rollback
303rollback sessionId conn@(InProcessConnection _ _ _) = executeGraphExpr sessionId conn Rollback
296rollback sessionId conn@(RemoteProcessConnection _ _) = remoteCall conn (ExecuteGraphExpr sessionId Rollback)
304rollback sessionId conn@(RemoteProcessConnection _ _) = remoteCall conn (ExecuteGraphExpr sessionId Rollback)
@@ -300,6 +308,7 @@ processPersistence NoPersistence _ = return ()
300processPersistence (MinimalPersistence dbdir) graph = transactionGraphPersist NoDiskSync dbdir graph
308processPersistence (MinimalPersistence dbdir) graph = transactionGraphPersist NoDiskSync dbdir graph
301processPersistence (CrashSafePersistence dbdir) graph = transactionGraphPersist FsyncDiskSync dbdir graph
309processPersistence (CrashSafePersistence dbdir) graph = transactionGraphPersist FsyncDiskSync dbdir graph
302
310
311+-- | Return a relation whose type would match that of the relational expression if it were executed. This is useful for checking types and validating a relational expression's types.
303typeForRelationalExpr :: SessionId -> Connection -> RelationalExpr -> IO (Either RelationalError Relation)
312typeForRelationalExpr :: SessionId -> Connection -> RelationalExpr -> IO (Either RelationalError Relation)
304typeForRelationalExpr sessionId conn@(InProcessConnection _ _ _) relExpr = atomically $ typeForRelationalExprSTM sessionId conn relExpr
313typeForRelationalExpr sessionId conn@(InProcessConnection _ _ _) relExpr = atomically $ typeForRelationalExprSTM sessionId conn relExpr
305typeForRelationalExpr sessionId conn@(RemoteProcessConnection _ _) relExpr = remoteCall conn (ExecuteTypeForRelationalExpr sessionId relExpr)
314typeForRelationalExpr sessionId conn@(RemoteProcessConnection _ _) relExpr = remoteCall conn (ExecuteTypeForRelationalExpr sessionId relExpr)
@@ -313,6 +322,7 @@ typeForRelationalExprSTM sessionId (InProcessConnection _ sessions _) relExpr =
313
322
314typeForRelationalExprSTM _ _ _ = error "typeForRelationalExprSTM called on non-local connection"
323typeForRelationalExprSTM _ _ _ = error "typeForRelationalExprSTM called on non-local connection"
315
324
325+-- | Return a 'Map' of the database's constraints at the context of the session and connection.
316inclusionDependencies :: SessionId -> Connection -> IO (Either RelationalError (M.Map IncDepName InclusionDependency))
326inclusionDependencies :: SessionId -> Connection -> IO (Either RelationalError (M.Map IncDepName InclusionDependency))
317inclusionDependencies sessionId (InProcessConnection _ sessions _) = do
327inclusionDependencies sessionId (InProcessConnection _ sessions _) = do
318 atomically $ do
328 atomically $ do
@@ -323,7 +333,7 @@ inclusionDependencies sessionId (InProcessConnection _ sessions _) = do
323
333
324inclusionDependencies sessionId conn@(RemoteProcessConnection _ _) = remoteCall conn (RetrieveInclusionDependencies sessionId)
334inclusionDependencies sessionId conn@(RemoteProcessConnection _ _) = remoteCall conn (RetrieveInclusionDependencies sessionId)
325
335
326−
336+-- | Return an optimized database expression which is logically equivalent to the input database expression. This function can be used to determine which expression will actually be evaluated.
327planForDatabaseContextExpr :: SessionId -> Connection -> DatabaseExpr -> IO (Either RelationalError DatabaseExpr)
337planForDatabaseContextExpr :: SessionId -> Connection -> DatabaseExpr -> IO (Either RelationalError DatabaseExpr)
328planForDatabaseContextExpr sessionId (InProcessConnection _ sessions _) dbExpr = do
338planForDatabaseContextExpr sessionId (InProcessConnection _ sessions _) dbExpr = do
329 atomically $ do
339 atomically $ do
@@ -333,6 +343,11 @@ planForDatabaseContextExpr sessionId (InProcessConnection _ sessions _) dbExpr =
333 Right session -> pure $ evalState (applyStaticDatabaseOptimization dbExpr) (sessionContext session)
343 Right session -> pure $ evalState (applyStaticDatabaseOptimization dbExpr) (sessionContext session)
334planForDatabaseContextExpr sessionId conn@(RemoteProcessConnection _ _) dbExpr = remoteCall conn (RetrievePlanForDatabaseContextExpr sessionId dbExpr)
344planForDatabaseContextExpr sessionId conn@(RemoteProcessConnection _ _) dbExpr = remoteCall conn (RetrievePlanForDatabaseContextExpr sessionId dbExpr)
335
345
346+-- | Return a relation which represents the current state of the global transaction graph. The attributes are
347+-- * current- boolean attribute representing whether or not the current session references this transaction
348+-- * head- text attribute which is a non-empty 'HeadName' iff the transaction references a head.
349+-- * id- UUID attribute of the transaction
350+-- * parents- a relation-valued attribute which contains a relation of UUIDs which are parent transaction to the transaction
336transactionGraphAsRelation :: SessionId -> Connection -> IO (Either RelationalError Relation)
351transactionGraphAsRelation :: SessionId -> Connection -> IO (Either RelationalError Relation)
337transactionGraphAsRelation sessionId (InProcessConnection _ sessions tvar) = do
352transactionGraphAsRelation sessionId (InProcessConnection _ sessions tvar) = do
338 atomically $ do
353 atomically $ do