module ProjectM36.Session where
import ProjectM36.Base
import Data.UUID
import qualified Data.Map as M
import ProjectM36.Error
import qualified ProjectM36.DisconnectedTransaction as Discon

type SessionId = UUID

--the persistence of a session is as long as the life of the database (not serialized to disk)
-- sessions are not associated with connections and have separate lifetimes
-- | Represents a pointer into the database's transaction graph which the 'DatabaseContextExpr's can then modify subsequently be committed to extend the transaction graph. The session contains staged (uncommitted) database changes as well as the means to switch between isomorphic schemas.
data Session = Session DisconnectedTransaction SchemaName

defaultSchemaName :: SchemaName
defaultSchemaName :: SchemaName
defaultSchemaName = SchemaName
"main"

disconnectedTransaction :: Session -> DisconnectedTransaction
disconnectedTransaction :: Session -> DisconnectedTransaction
disconnectedTransaction (Session DisconnectedTransaction
discon SchemaName
_) = DisconnectedTransaction
discon

isDirty :: Session -> DirtyFlag
isDirty :: Session -> DirtyFlag
isDirty (Session DisconnectedTransaction
discon SchemaName
_) = DisconnectedTransaction -> DirtyFlag
Discon.isDirty DisconnectedTransaction
discon

concreteDatabaseContext :: Session -> DatabaseContext
concreteDatabaseContext :: Session -> DatabaseContext
concreteDatabaseContext (Session (DisconnectedTransaction TransactionId
_ (Schemas DatabaseContext
context Subschemas
_) DirtyFlag
_) SchemaName
_) = DatabaseContext
context

parentId :: Session -> TransactionId
parentId :: Session -> TransactionId
parentId (Session (DisconnectedTransaction TransactionId
parentUUID Schemas
_ DirtyFlag
_) SchemaName
_) = TransactionId
parentUUID

subschemas :: Session -> Subschemas
subschemas :: Session -> Subschemas
subschemas (Session (DisconnectedTransaction TransactionId
_ (Schemas DatabaseContext
_ Subschemas
s) DirtyFlag
_) SchemaName
_) = Subschemas
s

schemas :: Session -> Schemas
schemas :: Session -> Schemas
schemas (Session (DisconnectedTransaction TransactionId
_ Schemas
s DirtyFlag
_) SchemaName
_) = Schemas
s

schemaName :: Session -> SchemaName
schemaName :: Session -> SchemaName
schemaName (Session DisconnectedTransaction
_ SchemaName
s) = SchemaName
s

setSchemaName :: SchemaName -> Session -> Either RelationalError Session
setSchemaName :: SchemaName -> Session -> Either RelationalError Session
setSchemaName SchemaName
sname Session
session = if SchemaName
sname SchemaName -> SchemaName -> DirtyFlag
forall a. Eq a => a -> a -> DirtyFlag
== SchemaName
defaultSchemaName DirtyFlag -> DirtyFlag -> DirtyFlag
|| SchemaName -> Subschemas -> DirtyFlag
forall k a. Ord k => k -> Map k a -> DirtyFlag
M.member SchemaName
sname (Session -> Subschemas
subschemas Session
session) then
                                Session -> Either RelationalError Session
forall (f :: * -> *) a. Applicative f => a -> f a
pure (DisconnectedTransaction -> SchemaName -> Session
Session (Session -> DisconnectedTransaction
disconnectedTransaction Session
session) SchemaName
sname)
                              else
                                RelationalError -> Either RelationalError Session
forall a b. a -> Either a b
Left (SchemaName -> RelationalError
SubschemaNameNotInUseError SchemaName
sname)