| Copyright | (c) digitally induced GmbH 2020 |
|---|---|
| Safe Haskell | None |
| Language | GHC2021 |
IHP.ModelSupport.Types
Description
This module contains the core types for IHP's model support. It's designed to be lightweight and avoid heavy dependencies, allowing modules that only need the types to compile faster.
For the full model API including query functions, use ModelSupport.
Synopsis
- data ModelContext = ModelContext {
- hasqlPool :: Pool
- transactionRunner :: Maybe TransactionRunner
- logger :: Logger
- trackTableReadCallback :: Maybe (Text -> IO ())
- rowLevelSecurity :: Maybe RowLevelSecurityContext
- data RowLevelSecurityContext = RowLevelSecurityContext {}
- newtype TransactionRunner = TransactionRunner {
- runInTransaction :: forall a. Session a -> IO a
- type family GetModelById id where ...
- type family GetTableName model :: Symbol
- type family GetModelByTableName (tableName :: Symbol)
- type family PrimaryKey (tableName :: Symbol)
- type family GetModelName model :: Symbol
- type family Include (name :: Symbol) model
- type family Include' (name :: [Symbol]) model where ...
- type NormalizeModel model = GetModelByTableName (GetTableName model)
- newtype Id' (table :: Symbol) = Id (PrimaryKey table)
- type Id model = Id' (GetTableName model)
- data MetaBag = MetaBag {
- annotations :: ![(Text, Violation)]
- touchedFields :: ![Text]
- originalDatabaseRecord :: Maybe Dynamic
- data Violation
- = TextViolation { }
- | HtmlViolation { }
- type FieldName = ByteString
- data FieldWithDefault valueType
- = Default
- | NonDefault valueType
- data FieldWithUpdate (name :: k) value
- data LabeledData a b = LabeledData {
- labelValue :: a
- contentValue :: b
- data RecordNotFoundException = RecordNotFoundException {}
- data EnhancedSqlError = EnhancedSqlError {}
- enhancedSqlErrorMessage :: EnhancedSqlError -> Text
- data HasqlSessionError = HasqlSessionError SessionError
- class CanCreate a where
- create :: a -> IO a
- createMany :: [a] -> IO [a]
- createRecordDiscardResult :: a -> IO ()
- class CanUpdate a where
- updateRecord :: a -> IO a
- updateRecordDiscardResult :: a -> IO ()
- class ParsePrimaryKey primaryKey where
- parsePrimaryKey :: Text -> Maybe primaryKey
Model Context
data ModelContext Source #
Provides the db connection and some IHP-specific db configuration
Constructors
| ModelContext | |
Fields
| |
Instances
| HasField "modelContext" Request ModelContext Source # | |
Defined in IHP.RequestVault.ModelContext Methods getField :: Request -> ModelContext # | |
data RowLevelSecurityContext Source #
When row level security is enabled at runtime, this keeps track of the current logged in user and the postgresql role to switch to.
Constructors
| RowLevelSecurityContext | |
Fields
| |
newtype TransactionRunner Source #
Runner that executes a hasql Session on the current transaction's connection
Constructors
| TransactionRunner | |
Fields
| |
Type Families
type family GetModelById id where ... Source #
Equations
| GetModelById (Maybe (Id' tableName)) = Maybe (GetModelByTableName tableName) | |
| GetModelById (Id' tableName) = GetModelByTableName tableName |
type family GetTableName model :: Symbol Source #
type family GetModelByTableName (tableName :: Symbol) Source #
type family PrimaryKey (tableName :: Symbol) Source #
Provides the primary key type for a given table. The instances are usually declared by the generated haskell code in Generated.Types
Example: Defining the primary key for a users table
type instance PrimaryKey "users" = UUID
Example: Defining the primary key for a table with a SERIAL pk
type instance PrimaryKey "projects" = Int
type family GetModelName model :: Symbol Source #
type NormalizeModel model = GetModelByTableName (GetTableName model) Source #
Helper type to deal with models where relations are included or that are only partially fetched Examples:
>>>NormalizeModel (Include "author_id" Post)Post
>>>NormalizeModel PostPost
Id Types
newtype Id' (table :: Symbol) Source #
Constructors
| Id (PrimaryKey table) |
Instances
| FromJSON (PrimaryKey a) => FromJSON (Id' a) Source # | |||||
| ToJSON (PrimaryKey a) => ToJSON (Id' a) Source # | |||||
| PrimaryKey table ~ UUID => Serialize (Id' table) Source # | |||||
| (KnownSymbol table, NFData (PrimaryKey table)) => NFData (Id' table) Source # | |||||
Defined in IHP.ModelSupport.Types | |||||
| (KnownSymbol table, Data (PrimaryKey table)) => Data (Id' table) Source # | |||||
Defined in IHP.ModelSupport.Types Methods gfoldl :: (forall d b. Data d => c (d -> b) -> d -> c b) -> (forall g. g -> c g) -> Id' table -> c (Id' table) # gunfold :: (forall b r. Data b => c (b -> r) -> c r) -> (forall r. r -> c r) -> Constr -> c (Id' table) # toConstr :: Id' table -> Constr # dataTypeOf :: Id' table -> DataType # dataCast1 :: Typeable t => (forall d. Data d => c (t d)) -> Maybe (c (Id' table)) # dataCast2 :: Typeable t => (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c (Id' table)) # gmapT :: (forall b. Data b => b -> b) -> Id' table -> Id' table # gmapQl :: (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> Id' table -> r # gmapQr :: forall r r'. (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> Id' table -> r # gmapQ :: (forall d. Data d => d -> u) -> Id' table -> [u] # gmapQi :: Int -> (forall d. Data d => d -> u) -> Id' table -> u # gmapM :: Monad m => (forall d. Data d => d -> m d) -> Id' table -> m (Id' table) # gmapMp :: MonadPlus m => (forall d. Data d => d -> m d) -> Id' table -> m (Id' table) # gmapMo :: MonadPlus m => (forall d. Data d => d -> m d) -> Id' table -> m (Id' table) # | |||||
| (Read (PrimaryKey model), ParsePrimaryKey (PrimaryKey model)) => IsString (Id' model) Source # | Sometimes you have a hardcoded UUID value which represents some record id. This instance allows you to write the Id like a string: let projectId = "ca63aace-af4b-4e6c-bcfa-76ca061dbdc6" :: Id Project | ||||
Defined in IHP.ModelSupport Methods fromString :: String -> Id' model # | |||||
| Show (PrimaryKey model) => Show (Id' model) Source # | |||||
| Eq (PrimaryKey table) => Eq (Id' table) Source # | |||||
| Ord (PrimaryKey table) => Ord (Id' table) Source # | |||||
| Hashable (PrimaryKey table) => Hashable (Id' table) Source # | |||||
| PrimaryKey table ~ UUID => DefaultParamEncoder (Id' table) Source # | Encode | ||||
Defined in IHP.Hasql.Encoders Methods defaultParam :: NullableOrNot Value (Id' table) Source # | |||||
| PrimaryKey table ~ UUID => DefaultParamEncoder (Maybe (Id' table)) Source # | Encode 'Maybe (Id' table)' for nullable foreign keys | ||||
Defined in IHP.Hasql.Encoders Methods defaultParam :: NullableOrNot Value (Maybe (Id' table)) Source # | |||||
| PrimaryKey table ~ UUID => DefaultParamEncoder [Id' table] Source # | Encode list of | ||||
Defined in IHP.Hasql.Encoders Methods defaultParam :: NullableOrNot Value [Id' table] Source # | |||||
| PrimaryKey table ~ UUID => DefaultParamEncoder [Maybe (Id' table)] Source # | Encode '[Maybe (Id' table)]' for filterWhereIn with nullable foreign keys | ||||
Defined in IHP.Hasql.Encoders Methods defaultParam :: NullableOrNot Value [Maybe (Id' table)] Source # | |||||
| (PrimaryKey a ~ UUID, PrimaryKey b ~ UUID) => DefaultParamEncoder [(Id' a, Id' b)] Source # | Encode '[(Id' a, Id' b)]' as PostgreSQL array of composite types Used by filterWhereIdIn for tables with composite primary keys of two Id columns | ||||
Defined in IHP.Hasql.Encoders Methods defaultParam :: NullableOrNot Value [(Id' a, Id' b)] Source # | |||||
| IsEmpty (PrimaryKey table) => IsEmpty (Id' table) Source # | |||||
| PrimaryKey table ~ UUID => HasqlDecodeValue (Id' table) Source # | |||||
Defined in IHP.Hasql.FromRow Methods hasqlDecodeValue :: Value (Id' table) Source # | |||||
| InputValue (PrimaryKey model') => InputValue (Id' model') Source # | |||||
Defined in IHP.ModelSupport Methods inputValue :: Id' model' -> Text Source # | |||||
| InputValue (PrimaryKey table) => ApplyAttribute (Id' table) | |||||
Defined in IHP.ViewSupport | |||||
| FromField (PrimaryKey model) => FromField (Id' model) Source # | |||||
Defined in IHP.PGSimpleCompat Methods fromField :: FieldParser (Id' model) Source # | |||||
| ToField (PrimaryKey model) => ToField (Id' model) Source # | |||||
| ParamReader (PrimaryKey model') => ParamReader (Id' model') Source # | |||||
Defined in IHP.Controller.Param Methods readParameter :: ByteString -> Either ByteString (Id' model') # readParameterJSON :: Value -> Either ByteString (Id' model') # | |||||
| (model ~ GetModelById (Id' table), GetTableName model ~ table, FilterPrimaryKey table) => Fetchable (Id' table) model Source # | |||||
Defined in IHP.Fetch Associated Types
| |||||
| (model ~ GetModelById (Id' table), GetTableName model ~ table, FilterPrimaryKey table) => Fetchable (Maybe (Id' table)) model Source # | |||||
Defined in IHP.Fetch Associated Types
| |||||
| (model ~ GetModelById (Id' table), GetModelByTableName table ~ model, GetTableName model ~ table, DefaultParamEncoder [PrimaryKey table]) => Fetchable [Id' table] model Source # | |||||
Defined in IHP.Fetch Associated Types
| |||||
| (TypeError (('Text "Looks like you forgot to pass a " ':<>: 'ShowType (GetModelByTableName record)) ':<>: 'Text " id to this data constructor.") :: Constraint) => Eq (Id' record -> controller) Source # | |||||
| (PrimaryKey a ~ UUID, PrimaryKey b ~ UUID) => DefaultParamEncoder (Id' a, Id' b) Source # | Encode '(Id' a, Id' b)' as PostgreSQL composite/record type Used for composite primary keys with two Id columns (where both resolve to UUID) | ||||
Defined in IHP.Hasql.Encoders Methods defaultParam :: NullableOrNot Value (Id' a, Id' b) Source # | |||||
| (ToField (Id' a), ToField (Id' b)) => ToField (Id' a, Id' b) Source # | |||||
| type FetchResult (Id' table) model Source # | |||||
Defined in IHP.Fetch | |||||
| type FetchResult (Maybe (Id' table)) model Source # | |||||
Defined in IHP.Fetch | |||||
| type FetchResult [Id' table] model Source # | |||||
Defined in IHP.Fetch | |||||
type Id model = Id' (GetTableName model) Source #
We need to map the model to its table name to prevent infinite recursion in the model data definition E.g. `type Project = Project' { id :: Id Project }` will not work But `type Project = Project' { id :: Id "projects" }` will
Record Metadata
Every IHP database record has a magic meta field which keeps a MetaBag inside. This data structure is used e.g. to keep track of the validation errors that happend.
Constructors
| MetaBag | |
Fields
| |
The error message of a validator can be either a plain text value or a HTML formatted value
Constructors
| TextViolation | Plain text validation error, like "cannot be empty" |
| HtmlViolation | HTML formatted, already pre-escaped validation error, like "Invalid, please href="http://example.com"check the documentation/a" |
type FieldName = ByteString Source #
Field Wrappers
data FieldWithDefault valueType Source #
Represents fields that have a default value in an SQL schema
The Default constructor represents the default value from the schema,
while the NonDefault constructor holds some other value for the field
Constructors
| Default | |
| NonDefault valueType |
Instances
| Show valueType => Show (FieldWithDefault valueType) Source # | |
Defined in IHP.ModelSupport.Types Methods showsPrec :: Int -> FieldWithDefault valueType -> ShowS # show :: FieldWithDefault valueType -> String # showList :: [FieldWithDefault valueType] -> ShowS # | |
| Eq valueType => Eq (FieldWithDefault valueType) Source # | |
Defined in IHP.ModelSupport.Types Methods (==) :: FieldWithDefault valueType -> FieldWithDefault valueType -> Bool # (/=) :: FieldWithDefault valueType -> FieldWithDefault valueType -> Bool # | |
| ToField valueType => ToField (FieldWithDefault valueType) Source # | |
Defined in IHP.PGSimpleCompat Methods toField :: FieldWithDefault valueType -> Action Source # | |
data FieldWithUpdate (name :: k) value Source #
Represents fields that may have been updated
The NoUpdate constructor represents the existing value in the database,
while the Update constructor holds some new value for the field
Instances
| Show value => Show (FieldWithUpdate name value) Source # | |
Defined in IHP.ModelSupport.Types Methods showsPrec :: Int -> FieldWithUpdate name value -> ShowS # show :: FieldWithUpdate name value -> String # showList :: [FieldWithUpdate name value] -> ShowS # | |
| Eq value => Eq (FieldWithUpdate name value) Source # | |
Defined in IHP.ModelSupport.Types Methods (==) :: FieldWithUpdate name value -> FieldWithUpdate name value -> Bool # (/=) :: FieldWithUpdate name value -> FieldWithUpdate name value -> Bool # | |
| (KnownSymbol name, ToField value) => ToField (FieldWithUpdate name value) Source # | |
Defined in IHP.PGSimpleCompat Methods toField :: FieldWithUpdate name value -> Action Source # | |
Utility Types
data LabeledData a b Source #
Record type for objects of model types labeled with values from different database tables. (e.g. comments labeled with the IDs of the posts they belong to).
Constructors
| LabeledData | |
Fields
| |
Instances
| (Show a, Show b) => Show (LabeledData a b) Source # | |
Defined in IHP.ModelSupport.Types Methods showsPrec :: Int -> LabeledData a b -> ShowS # show :: LabeledData a b -> String # showList :: [LabeledData a b] -> ShowS # | |
| (HasqlDecodeColumn label, FromRowHasql a) => FromRowHasql (LabeledData label a) Source # | |
Defined in IHP.Hasql.FromRow Methods hasqlRowDecoder :: Row (LabeledData label a) Source # | |
| (FromField label, FromRow a) => FromRow (LabeledData label a) Source # | |
Defined in IHP.PGSimpleCompat Methods fromRow :: RowParser (LabeledData label a) Source # | |
Exceptions
data RecordNotFoundException Source #
Thrown by fetchOne when the query result is empty
Constructors
| RecordNotFoundException | |
Fields | |
Instances
| Exception RecordNotFoundException Source # | |
Defined in IHP.ModelSupport.Types | |
| Show RecordNotFoundException Source # | |
Defined in IHP.ModelSupport.Types Methods showsPrec :: Int -> RecordNotFoundException -> ShowS # show :: RecordNotFoundException -> String # showList :: [RecordNotFoundException] -> ShowS # | |
data EnhancedSqlError Source #
Whenever calls to query or execute
raise an SqlError exception, we wrap that exception in this data structure.
This allows us to show the actual database query that has triggered the error.
Constructors
| EnhancedSqlError | |
Fields | |
Instances
| Exception EnhancedSqlError Source # | |
Defined in IHP.ModelSupport.Types Methods toException :: EnhancedSqlError -> SomeException # fromException :: SomeException -> Maybe EnhancedSqlError # | |
| Show EnhancedSqlError Source # | |
Defined in IHP.ModelSupport.Types Methods showsPrec :: Int -> EnhancedSqlError -> ShowS # show :: EnhancedSqlError -> String # showList :: [EnhancedSqlError] -> ShowS # | |
enhancedSqlErrorMessage :: EnhancedSqlError -> Text Source #
Extract the SQL error message as Text from an EnhancedSqlError.
This avoids downstream packages needing to import postgresql-simple
to access the sqlErrorMsg field on SqlError.
data HasqlSessionError Source #
Wrapper to make SessionError an Exception, since it doesn't have one by default
Constructors
| HasqlSessionError SessionError |
Instances
| Exception HasqlSessionError Source # | |
Defined in IHP.ModelSupport.Types Methods toException :: HasqlSessionError -> SomeException # fromException :: SomeException -> Maybe HasqlSessionError # | |
| Show HasqlSessionError Source # | |
Defined in IHP.ModelSupport.Types Methods showsPrec :: Int -> HasqlSessionError -> ShowS # show :: HasqlSessionError -> String # showList :: [HasqlSessionError] -> ShowS # | |
Type Classes
class CanUpdate a where Source #
Minimal complete definition
Methods
updateRecord :: a -> IO a Source #
updateRecordDiscardResult :: a -> IO () Source #
Like updateRecord but doesn't return the updated record
class ParsePrimaryKey primaryKey where Source #
Methods
parsePrimaryKey :: Text -> Maybe primaryKey Source #
Instances
| ParsePrimaryKey Text Source # | |
Defined in IHP.ModelSupport | |
| ParsePrimaryKey UUID Source # | |
Defined in IHP.ModelSupport | |