on 18f736a help sign in
527 lines 28 kB history raw
1{-# LANGUAGE ExistentialQuantification,DeriveGeneric,DeriveAnyClass, TypeSynonymInstances, FlexibleInstances #-}
2{-# OPTIONS_GHC -fno-warn-orphans #-}
3module ProjectM36.Base where
4import ProjectM36.DatabaseContextFunctionError
5import ProjectM36.AtomFunctionError
7import qualified Data.Map as M
8import qualified Data.HashSet as HS
9import Data.Hashable (Hashable, hashWithSalt)
10import qualified Data.Set as S
11import Data.UUID (UUID)
12import Control.DeepSeq (NFData, rnf)
13import Control.DeepSeq.Generics (genericRnf)
14import GHC.Generics (Generic)
15import qualified Data.Vector as V
16import qualified Data.List as L
17import Data.Text (Text,unpack)
18import Data.Binary
19import Data.Vector.Binary()
20import Data.Time.Clock
21import Data.Time.Clock.POSIX
22import Data.Time.Calendar (Day,toGregorian,fromGregorian)
23import Data.Hashable.Time ()
24import Data.Typeable
25import Data.ByteString (ByteString)
27type StringType = Text
29-- | Database atoms are the smallest, undecomposable units of a tuple. Common examples are integers, text, or unique identity keys.
30data Atom = IntegerAtom Integer |
31 IntAtom Int |
32 DoubleAtom Double |
33 TextAtom Text |
34 DayAtom Day |
35 DateTimeAtom UTCTime |
36 ByteStringAtom ByteString |
37 BoolAtom Bool |
38 IntervalAtom Atom Atom OpenInterval OpenInterval |
39 RelationAtom Relation |
40 ConstructedAtom DataConstructorName AtomType [Atom]
41 deriving (Eq, Show, Binary, Typeable, NFData, Generic)
43type OpenInterval = Bool
45instance Hashable Atom where
46 hashWithSalt salt (ConstructedAtom dConsName _ atoms) = salt `hashWithSalt` atoms
47 `hashWithSalt` dConsName --AtomType is not hashable
48 hashWithSalt salt (IntAtom i) = salt `hashWithSalt` i
49 hashWithSalt salt (IntegerAtom i) = salt `hashWithSalt` i
50 hashWithSalt salt (DoubleAtom d) = salt `hashWithSalt` d
51 hashWithSalt salt (TextAtom t) = salt `hashWithSalt` t
52 hashWithSalt salt (DayAtom d) = salt `hashWithSalt` d
53 hashWithSalt salt (DateTimeAtom dt) = salt `hashWithSalt` dt
54 hashWithSalt salt (ByteStringAtom bs) = salt `hashWithSalt` bs
55 hashWithSalt salt (BoolAtom b) = salt `hashWithSalt` b
56 hashWithSalt salt (IntervalAtom a1 a2 bo be) = salt `hashWithSalt` a1 `hashWithSalt` a2 `hashWithSalt` bo `hashWithSalt` be
57 hashWithSalt salt (RelationAtom r) = salt `hashWithSalt` r
59instance Binary UTCTime where
60 put utc = put $ toRational (utcTimeToPOSIXSeconds utc)
61 get = do
62 r <- get :: Get Rational
63 return (posixSecondsToUTCTime (fromRational r))
65instance Binary Day where
66 put day = put $ toGregorian day
67 get = do
68 (y,m,d) <- get :: Get (Integer, Int, Int)
69 return (fromGregorian y m d)
71-- I suspect the definition of ConstructedAtomType with its name alone is insufficient to disambiguate the cases; for example, one could create a type named X, remove a type named X, and re-add it using different constructors. However, as long as requests are served from only one DatabaseContext at-a-time, the type name is unambiguous. This will become a problem for time-travel, however.
72-- | The AtomType uniquely identifies the type of a atom.
73data AtomType = IntAtomType |
74 IntegerAtomType |
75 DoubleAtomType |
76 TextAtomType |
77 DayAtomType |
78 DateTimeAtomType |
79 ByteStringAtomType |
80 BoolAtomType |
81 IntervalAtomType AtomType |
82 RelationAtomType Attributes |
83 ConstructedAtomType TypeConstructorName TypeVarMap |
84 TypeVariableType TypeVarName
85 --wildcard used in Atom Functions and tuples for data constructors which don't provide all arguments to the type constructor
86 deriving (Eq, NFData, Generic, Binary, Show)
88type TypeVarMap = M.Map TypeVarName AtomType
90instance Hashable TypeVarMap where
91 hashWithSalt salt tvmap = hashWithSalt salt (M.keys tvmap)
93-- | Return True iff the atom type argument is relation-valued. If True, this indicates that the Atom contains a relation.
94isRelationAtomType :: AtomType -> Bool
95isRelationAtomType (RelationAtomType _) = True
96isRelationAtomType _ = False
98-- | The AttributeName is the name of an attribute in a relation.
99type AttributeName = StringType
101-- | A relation's type is composed of attribute names and types.
102data Attribute = Attribute AttributeName AtomType deriving (Eq, Show, Generic, NFData, Binary)
104instance Hashable Attribute where
105 hashWithSalt salt (Attribute attrName _) = hashWithSalt salt attrName
107-- | 'Attributes' represent the head of a relation.
108type Attributes = V.Vector Attribute
110-- | Equality function for a set of attributes.
111attributesEqual :: Attributes -> Attributes -> Bool
112attributesEqual attrs1 attrs2 = attrsAsSet attrs1 == attrsAsSet attrs2
113 where
114 attrsAsSet = HS.fromList . V.toList
116sortedAttributesIndices :: Attributes -> [(Int, Attribute)]
117sortedAttributesIndices attrs = L.sortBy (\(_, Attribute name1 _) (_,Attribute name2 _) -> compare name1 name2) $ V.toList (V.indexed attrs)
119-- | The relation's tuple set is the body of the relation.
120newtype RelationTupleSet = RelationTupleSet { asList :: [RelationTuple] } deriving (Hashable, Show, Generic, Binary)
122instance Read Relation where
123 readsPrec = error "relation read not supported"
125instance Eq RelationTupleSet where
126 set1 == set2 = hset set1 == hset set2
127 where
128 hset = HS.fromList . asList
130instance NFData RelationTupleSet where rnf = genericRnf
132--the same hash must be generated for equal tuples so that the hashset equality works
133instance Hashable RelationTuple where
134 --sanity check the tuple for attribute and tuple counts
135 --this bit me when tuples were being hashed before being verified
136 hashWithSalt salt (RelationTuple attrs tupVec) = if V.length attrs /= V.length tupVec then
137 error "invalid tuple: attributes and tuple count mismatch"
138 else
139 salt `hashWithSalt`
140 sortedAttrs `hashWithSalt`
141 V.toList sortedTupVec
142 where
143 sortedAttrsIndices = sortedAttributesIndices attrs
144 sortedAttrs = map snd sortedAttrsIndices
145 sortedTupVec = V.map (\(index, _) -> tupVec V.! index) $ V.fromList sortedAttrsIndices
147-- | A tuple is a set of attributes mapped to their 'Atom' values.
148data RelationTuple = RelationTuple Attributes (V.Vector Atom) deriving (Show, Generic)
150instance Binary RelationTuple
152instance Eq RelationTuple where
153 (==) tuple1@(RelationTuple attrs1 _) tuple2@(RelationTuple attrs2 _) = attributesEqual attrs1 attrs2 && atomsEqual
154 where
155 atomForAttribute attr (RelationTuple attrs tupVec) = case V.findIndex (== attr) attrs of
156 Nothing -> Nothing
157 Just index -> tupVec V.!? index
158 atomsEqual = V.all (== True) $ V.map (\attr -> atomForAttribute attr tuple1 == atomForAttribute attr tuple2) attrs1
160instance NFData RelationTuple where rnf = genericRnf
162data Relation = Relation Attributes RelationTupleSet deriving (Show, Generic,Typeable)
164instance Eq Relation where
165 Relation attrs1 tupSet1 == Relation attrs2 tupSet2 = attributesEqual attrs1 attrs2 && tupSet1 == tupSet2
167instance NFData Relation where rnf = genericRnf
169instance Hashable Relation where
170 hashWithSalt salt (Relation attrs tupSet) = salt `hashWithSalt`
171 sortedAttrs `hashWithSalt`
172 asList tupSet
173 where
174 sortedAttrs = map snd (sortedAttributesIndices attrs)
176instance Binary Relation
178-- | Used to represent the number of tuples in a relation.
179data RelationCardinality = Countable | Finite Int deriving (Eq, Show, Generic, Ord)
181-- | Relation variables are identified by their names.
182type RelVarName = StringType
184type RelationalExpr = RelationalExprBase ()
186-- | A relational expression represents query (read) operations on a database.
187data RelationalExprBase a =
188 --- | Create a relation from tuple expressions.
189 MakeRelationFromExprs (Maybe [AttributeExprBase a]) [TupleExprBase a] |
190 --- | Create and reference a relation from attributes and a tuple set.
191 MakeStaticRelation Attributes RelationTupleSet |
192 --- | Reference an existing relation in Haskell-space.
193 ExistingRelation Relation |
194 --MakeFunctionalRelation (creates a relation from a tuple-generating function, potentially infinite)
195 --in Tutorial D, relational variables pick up the type of the first relation assigned to them
196 --relational variables should also be able to be explicitly-typed like in Haskell
197 --- | Reference a relation variable by its name.
198 RelationVariable RelVarName a |
199 --- | Create a projection over attribute names. (Note that the 'AttributeNames' structure allows for the names to be inverted.)
200 Project (AttributeNamesBase a) (RelationalExprBase a) |
201 --- | Create a union of two relational expressions. The expressions should have identical attributes.
202 Union (RelationalExprBase a) (RelationalExprBase a) |
203 --- | 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.
204 Join (RelationalExprBase a) (RelationalExprBase a) |
205 --- | Rename an attribute (first argument) to another (second argument).
206 Rename AttributeName AttributeName (RelationalExprBase a) |
207 --- | Return a relation containing all tuples of the first argument which do not appear in the second argument (minus).
208 Difference (RelationalExprBase a) (RelationalExprBase a) |
209 --- | 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.>
210 Group (AttributeNamesBase a) AttributeName (RelationalExprBase a) |
211 --- | 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.
212 Ungroup AttributeName (RelationalExprBase a) |
213 --- | Filter the tuples of the relational expression to only retain the tuples which evaluate against the restriction predicate to true.
214 Restrict (RestrictionPredicateExprBase a) (RelationalExprBase a) |
215 --- | Returns the true relation iff
216 Equals (RelationalExprBase a) (RelationalExprBase a) |
217 NotEquals (RelationalExprBase a) (RelationalExprBase a) |
218 Extend (ExtendTupleExprBase a) (RelationalExprBase a)
219 --Summarize :: AtomExpr -> AttributeName -> RelationalExpr -> RelationalExpr -> RelationalExpr -- a special case of Extend
220 deriving (Show, Eq, Generic, NFData)
222instance Binary RelationalExpr
224type NotificationName = StringType
225type Notifications = M.Map NotificationName Notification
227-- | When the changeExpr returns a different result in the database context, then the reportExpr is triggered and sent asynchronously to all clients.
228data Notification = Notification {
229 changeExpr :: RelationalExpr,
230 reportOldExpr :: RelationalExpr, --run the expression in the pre-change context
231 reportNewExpr :: RelationalExpr --run the expression in the post-change context
232 }
233 deriving (Show, Eq, Binary, Generic, NFData)
235type TypeVarName = StringType
237-- | Metadata definition for type constructors such as @data Either a b@.
238data TypeConstructorDef = ADTypeConstructorDef TypeConstructorName [TypeVarName] |
239 PrimitiveTypeConstructorDef TypeConstructorName AtomType
240 deriving (Show, Generic, Binary, Eq, NFData)
242-- | Found in data constructors and type declarations: Left (Either Int Text) | Right Int
243data TypeConstructor = ADTypeConstructor TypeConstructorName [TypeConstructor] |
244 PrimitiveTypeConstructor TypeConstructorName AtomType |
245 TypeVariable TypeVarName
246 deriving (Show, Generic, Binary, Eq, NFData)
248type TypeConstructorMapping = [(TypeConstructorDef, DataConstructorDefs)]
250type TypeConstructorName = StringType
251type TypeConstructorArgName = StringType
252type DataConstructorName = StringType
253type AtomTypeName = StringType
255-- | Used to define a data constructor in a type constructor context such as @Left a | Right b@
256data DataConstructorDef = DataConstructorDef DataConstructorName [DataConstructorDefArg] deriving (Eq, Show, Binary, Generic, NFData)
258type DataConstructorDefs = [DataConstructorDef]
260data DataConstructorDefArg = DataConstructorDefTypeConstructorArg TypeConstructor |
261 DataConstructorDefTypeVarNameArg TypeVarName
262 deriving (Show, Generic, Binary, Eq, NFData)
264type InclusionDependencies = M.Map IncDepName InclusionDependency
265type RelationVariables = M.Map RelVarName Relation
267type SchemaName = StringType
269type Subschemas = M.Map SchemaName Schema
271-- | Every transaction has one concrete database context and any number of isomorphic subschemas.
272data Schemas = Schemas DatabaseContext Subschemas
274-- | The DatabaseContext is a snapshot of a database's evolving state and contains everything a database client can change over time.
275-- I spent some time thinking about whether the VirtualDatabaseContext/Schema and DatabaseContext data constructors should be the same constructor, but that would allow relation variables to be created in a "virtual" context which would appear to defeat the isomorphisms of the contexts. It should be possible to switch to an alternative schema to view the same equivalent information without information loss. However, allowing all contexts to reference another context while maintaining its own relation variables, new types, etc. could be interesting from a security perspective. For example, if a user creates a new relvar in a virtual context, then does it necessarily appear in all linked contexts? After deliberation, I think the relvar should appear in *all* linked contexts to retain the isomorphic properties, even when the isomorphism is for a subset of the context. This hints that the IsoMorphs should allow for "fall-through"; that is, when a relvar is not defined in the virtual context (for morphing), then the lookup should fall through to the underlying context.
276newtype Schema = Schema SchemaIsomorphs
277 deriving (Generic, Binary)
279data SchemaIsomorph = IsoRestrict RelVarName RestrictionPredicateExpr (RelVarName, RelVarName) |
280 IsoRename RelVarName RelVarName |
281 IsoUnion (RelVarName, RelVarName) RestrictionPredicateExpr RelVarName --maps two relvars to one relvar
282 -- IsoTypeConstructor in morphAttrExpr
283 deriving (Generic, Binary, Show)
285type SchemaIsomorphs = [SchemaIsomorph]
287data DatabaseContext = DatabaseContext {
288 inclusionDependencies :: InclusionDependencies,
289 relationVariables :: RelationVariables,
290 atomFunctions :: AtomFunctions,
291 dbcFunctions :: DatabaseContextFunctions,
292 notifications :: Notifications,
293 typeConstructorMapping :: TypeConstructorMapping
294 } deriving (NFData, Generic)
296type IncDepName = StringType
298-- | Inclusion dependencies represent every possible database constraint. Constraints enforce specific, arbitrarily-complex rules to which the database context's relation variables must adhere unconditionally.
299data InclusionDependency = InclusionDependency RelationalExpr RelationalExpr deriving (Show, Eq, Generic, NFData)
301instance Binary InclusionDependency
303type AttributeNameAtomExprMap = M.Map AttributeName AtomExpr
305--used for returning information about individual expressions
306type DatabaseContextExprName = StringType
308-- | Database context expressions modify the database context.
309data DatabaseContextExpr =
310 NoOperation |
311 Define RelVarName [AttributeExpr] |
312 Undefine RelVarName | --forget existence of relvar X
313 Assign RelVarName RelationalExpr |
314 Insert RelVarName RelationalExpr |
315 Delete RelVarName RestrictionPredicateExpr |
316 Update RelVarName AttributeNameAtomExprMap RestrictionPredicateExpr |
318 AddInclusionDependency IncDepName InclusionDependency |
319 RemoveInclusionDependency IncDepName |
321 AddNotification NotificationName RelationalExpr RelationalExpr RelationalExpr |
322 RemoveNotification NotificationName |
324 AddTypeConstructor TypeConstructorDef [DataConstructorDef] |
325 RemoveTypeConstructor TypeConstructorName |
327 --adding an AtomFunction is not a pure operation (required loading GHC modules)
328 RemoveAtomFunction AtomFunctionName |
330 RemoveDatabaseContextFunction DatabaseContextFunctionName |
332 ExecuteDatabaseContextFunction DatabaseContextFunctionName [AtomExpr] |
334 MultipleExpr [DatabaseContextExpr]
335 deriving (Show, Eq, Binary, Generic)
337-- | Adding an atom function should be nominally a DatabaseExpr except for the fact that it cannot be performed purely. Thus, we create the DatabaseContextIOExpr.
338data DatabaseContextIOExpr = AddAtomFunction AtomFunctionName [TypeConstructor] AtomFunctionBodyScript |
339 AddDatabaseContextFunction DatabaseContextFunctionName [TypeConstructor] DatabaseContextFunctionBodyScript
340 deriving (Show, Eq, Generic, Binary)
343type RestrictionPredicateExpr = RestrictionPredicateExprBase ()
345-- | Restriction predicates are boolean algebra components which, when composed, indicate whether or not a tuple should be retained during a restriction (filtering) operation.
346data RestrictionPredicateExprBase a =
347 TruePredicate |
348 AndPredicate (RestrictionPredicateExprBase a) (RestrictionPredicateExprBase a) |
349 OrPredicate (RestrictionPredicateExprBase a) (RestrictionPredicateExprBase a) |
350 NotPredicate (RestrictionPredicateExprBase a) |
351 RelationalExprPredicate (RelationalExprBase a) | --type must be same as true and false relations (no attributes)
352 AtomExprPredicate (AtomExprBase a) | --atom must evaluate to boolean
353 AttributeEqualityPredicate AttributeName (AtomExprBase a) -- relationalexpr must result in relation with single tuple
354 deriving (Show, Eq, Generic, NFData)
356instance Binary RestrictionPredicateExpr
358-- child + parent links
359-- | 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.
360type HeadName = StringType
362type TransactionHeads = M.Map HeadName Transaction
364-- | The transaction graph is the global database's state which references every committed transaction.
365data TransactionGraph = TransactionGraph TransactionHeads (S.Set Transaction)
367transactionsForGraph :: TransactionGraph -> S.Set Transaction
368transactionsForGraph (TransactionGraph _ t) = t
370transactionHeadsForGraph :: TransactionGraph -> TransactionHeads
371transactionHeadsForGraph (TransactionGraph heads _) = heads
373-- | Every transaction has context-specific information attached to it.
374data TransactionInfo = TransactionInfo TransactionId (S.Set TransactionId) UTCTime | -- 1 parent + n children
375 MergeTransactionInfo TransactionId TransactionId (S.Set TransactionId) UTCTime -- 2 parents, n children
376 deriving(Show, Generic)
378instance Binary TransactionInfo
380-- | Every set of modifications made to the database are atomically committed to the transaction graph as a transaction.
381type TransactionId = UUID
383data Transaction = Transaction TransactionId TransactionInfo Schemas
385--instance Binary Transaction
387type DirtyFlag = Bool
389-- | 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.
390data DisconnectedTransaction = DisconnectedTransaction TransactionId Schemas DirtyFlag --parentID, context- the context here represents the singular concrete context from the schema
391--the dirty flag indicates that the database context has diverged from its parent's context
393transactionId :: Transaction -> TransactionId
394transactionId (Transaction tid _ _) = tid
396transactionInfo :: Transaction -> TransactionInfo
397transactionInfo (Transaction _ info _) = info
399instance Eq Transaction where
400 (Transaction uuidA _ _) == (Transaction uuidB _ _) = uuidA == uuidB
402instance Ord Transaction where
403 compare (Transaction uuidA _ _) (Transaction uuidB _ _) = compare uuidA uuidB
405type AtomExpr = AtomExprBase ()
407-- | An atom expression represents an action to take when extending a relation or when statically defining a relation or a new tuple.
408data AtomExprBase a = AttributeAtomExpr AttributeName |
409 NakedAtomExpr Atom |
410 FunctionAtomExpr AtomFunctionName [AtomExprBase a] a |
411 RelationAtomExpr (RelationalExprBase a) |
412 ConstructedAtomExpr DataConstructorName [AtomExprBase a] a
413 deriving (Eq,Show,Generic, NFData)
415instance Binary AtomExpr
417-- | Used in tuple creation when creating a relation.
418data ExtendTupleExprBase a = AttributeExtendTupleExpr AttributeName (AtomExprBase a)
419 deriving (Show, Eq, Generic, NFData)
421type ExtendTupleExpr = ExtendTupleExprBase ()
423instance Binary ExtendTupleExpr
425--enumerates the list of functions available to be run as part of tuple expressions
426type AtomFunctions = HS.HashSet AtomFunction
428type AtomFunctionName = StringType
430type AtomFunctionBodyScript = StringType
432type AtomFunctionBodyType = [Atom] -> Either AtomFunctionError Atom
434data AtomFunctionBody = AtomFunctionBody (Maybe AtomFunctionBodyScript) AtomFunctionBodyType
436instance NFData AtomFunctionBody where
437 rnf (AtomFunctionBody mScript _) = rnf mScript
439instance Show AtomFunctionBody where
440 show (AtomFunctionBody mScript _) = case mScript of
441 Just script -> show (unpack script)
442 Nothing -> "<compiled>"
444-- | An AtomFunction has a name, a type, and a function body to execute when called.
445data AtomFunction = AtomFunction {
446 atomFuncName :: AtomFunctionName,
447 atomFuncType :: [AtomType],
448 atomFuncBody :: AtomFunctionBody
449 } deriving (Generic, NFData)
451instance Hashable AtomFunction where
452 hashWithSalt salt func = salt `hashWithSalt` atomFuncName func
454instance Eq AtomFunction where
455 f1 == f2 = atomFuncName f1 == atomFuncName f2
457instance Show AtomFunction where
458 show aFunc = unpack (atomFuncName aFunc) ++ "::" ++ showArgTypes ++ "; " ++ body
459 where
460 body = show (atomFuncBody aFunc)
461 showArgTypes = L.intercalate "->" (map show (atomFuncType aFunc))
463-- | 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").
464data AttributeNamesBase a = AttributeNames (S.Set AttributeName) |
465 InvertedAttributeNames (S.Set AttributeName) |
466 UnionAttributeNames (AttributeNamesBase a) (AttributeNamesBase a) |
467 IntersectAttributeNames (AttributeNamesBase a) (AttributeNamesBase a) |
468 RelationalExprAttributeNames (RelationalExprBase a) -- use attribute names from the relational expression's type
469 deriving (Eq, Show, Generic, NFData)
471type AttributeNames = AttributeNamesBase ()
472instance Binary AttributeNames
474-- | The persistence strategy is a global database option which represents how to persist the database in the filesystem, if at all.
475data PersistenceStrategy = NoPersistence | -- ^ no filesystem persistence/memory-only database
476 MinimalPersistence FilePath | -- ^ fsync off, not crash-safe
477 CrashSafePersistence FilePath -- ^ full fsync to disk (flushes kernel and physical drive buffers to ensure that the transaction is on non-volatile storage)
478 deriving (Show, Read)
480type AttributeExpr = AttributeExprBase ()
482-- | Create attributes dynamically.
483data AttributeExprBase a = AttributeAndTypeNameExpr AttributeName TypeConstructor a |
484 NakedAttributeExpr Attribute
485 deriving (Eq, Show, Generic, Binary, NFData)
487-- | Dynamically create a tuple from attribute names and 'AtomExpr's.
488newtype TupleExprBase a = TupleExpr (M.Map AttributeName (AtomExprBase a))
489 deriving (Eq, Show, Generic, NFData)
491instance Binary TupleExpr
493type TupleExpr = TupleExprBase ()
495data MergeStrategy =
496 -- | After a union merge, the merge transaction is a result of union'ing relvars of the same name, introducing all uniquely-named relvars, union of constraints, union of atom functions, notifications, and types (unless the names and definitions collide, e.g. two types of the same name with different definitions)
497 UnionMergeStrategy |
498 -- | Similar to a union merge, but, on conflict, prefer the unmerged section (relvar, function, etc.) from the branch named as the argument.
499 UnionPreferMergeStrategy HeadName |
500 -- | Similar to the our/theirs merge strategy in git, the merge transaction's context is identical to that of the last transaction in the selected branch.
501 SelectedBranchMergeStrategy HeadName
502 deriving (Eq, Show, Binary, Generic, NFData)
504type DatabaseContextFunctionName = StringType
506type DatabaseContextFunctionBodyScript = StringType
508type DatabaseContextFunctionBodyType = [Atom] -> DatabaseContext -> Either DatabaseContextFunctionError DatabaseContext
510data DatabaseContextFunctionBody = DatabaseContextFunctionBody (Maybe DatabaseContextFunctionBodyScript) DatabaseContextFunctionBodyType
512instance NFData DatabaseContextFunctionBody where
513 rnf (DatabaseContextFunctionBody mScript _) = rnf mScript
515data DatabaseContextFunction = DatabaseContextFunction {
516 dbcFuncName :: DatabaseContextFunctionName,
517 dbcFuncType :: [AtomType],
518 dbcFuncBody :: DatabaseContextFunctionBody
519 } deriving (Generic, NFData)
521type DatabaseContextFunctions = HS.HashSet DatabaseContextFunction
523instance Hashable DatabaseContextFunction where
524 hashWithSalt salt func = salt `hashWithSalt` dbcFuncName func
526instance Eq DatabaseContextFunction where
527 f1 == f2 = dbcFuncName f1 == dbcFuncName f2