Safe Haskell | None |
---|---|
Language | Haskell2010 |
Selda is not LINQ, but they're definitely related.
Selda is a high-level EDSL for interacting with relational databases.
All database computations are performed within some monad implementing
the MonadSelda
type class. The SeldaT
monad over any MonadIO
is the
only pre-defined instance of MonadSelda
.
SeldaM
is provided as a convenient short-hand for SeldaT IO
.
To actually execute a database computation, you need one of the database
backends: selda-sqlite
or selda-postgresql
.
All Selda functions may throw SeldaError
when something goes wrong.
This includes database connection errors, uniqueness constraint errors,
etc.
See https://selda.link/tutorial for a tutorial covering the language basics.
Synopsis
- class MonadIO m => MonadSelda m
- type family Backend m
- data SeldaError
- data ValidationError
- data SeldaT b m a
- type SeldaM b = SeldaT b IO
- type Relational a = (Generic a, SqlRow a, GRelation (Rep a))
- newtype Only a = Only a
- class The a where
- data Table a
- data Query s a
- data Row s a
- data Col s a
- type family Res r where ...
- class Typeable (Res r) => Result r
- query :: (MonadSelda m, Result a) => Query (Backend m) a -> m [Res a]
- queryInto :: (MonadSelda m, Relational a) => Table a -> Query (Backend m) (Row (Backend m) a) -> m Int
- transaction :: (MonadSelda m, MonadMask m) => m a -> m a
- withoutForeignKeyEnforcement :: (MonadSelda m, MonadMask m) => m a -> m a
- newUuid :: MonadIO m => m UUID
- class Typeable a => SqlType a where
- mkLit :: a -> Lit a
- sqlType :: Proxy a -> SqlTypeRep
- fromSql :: SqlValue -> a
- defaultValue :: Lit a
- class Typeable a => SqlRow a where
- nextResult :: ResultReader a
- nestedCols :: Proxy a -> Int
- class (Typeable a, Bounded a, Enum a) => SqlEnum a where
- class Columns a
- class s ~ t => Same s t
- data Order
- data a :*: b where
- select :: Relational a => Table a -> Query s (Row s a)
- selectValues :: forall s a. Relational a => [a] -> Query s (Row s a)
- from :: (Typeable t, SqlType a) => Selector t a -> Query s (Row s t) -> Query s (Col s a)
- distinct :: (Columns a, Columns (OuterCols a)) => Query (Inner s) a -> Query s (OuterCols a)
- restrict :: Same s t => Col s Bool -> Query t ()
- limit :: Same s t => Int -> Int -> Query (Inner s) a -> Query t (OuterCols a)
- order :: (Same s t, SqlType a) => Col s a -> Order -> Query t ()
- ascending :: Order
- descending :: Order
- orderRandom :: Query s ()
- inner :: (Columns a, Columns (OuterCols a)) => Query (Inner s) a -> Query s (OuterCols a)
- suchThat :: (Columns a, Columns (OuterCols a)) => Query (Inner s) a -> (a -> Col (Inner s) Bool) -> Query s (OuterCols a)
- data Selector t a
- type family Coalesce a where ...
- class (Relational t, SqlType (FieldType name t), GRSel name (Rep t), NonError (FieldType name t)) => HasField (name :: Symbol) t
- type FieldType name t = GFieldType (Rep t) (NoSuchSelector t name) name
- class IsLabel (x :: Symbol) a
- (!) :: SqlType a => Row s t -> Selector t a -> Col s a
- (?) :: SqlType a => Row s (Maybe t) -> Selector t a -> Col s (Coalesce (Maybe a))
- data Assignment s a where
- (:=) :: Selector t a -> Col s a -> Assignment s t
- with :: Row s a -> [Assignment s a] -> Row s a
- (+=) :: (SqlType a, Num (Col s a)) => Selector t a -> Col s a -> Assignment s t
- (-=) :: (SqlType a, Num (Col s a)) => Selector t a -> Col s a -> Assignment s t
- (*=) :: (SqlType a, Num (Col s a)) => Selector t a -> Col s a -> Assignment s t
- (||=) :: Selector t Bool -> Col s Bool -> Assignment s t
- (&&=) :: Selector t Bool -> Col s Bool -> Assignment s t
- ($=) :: Selector t a -> (Col s a -> Col s a) -> Assignment s t
- class Set set where
- data ID a
- invalidId :: ID a
- isInvalidId :: ID a -> Bool
- untyped :: ID a -> RowID
- fromId :: ID a -> Int
- toId :: Int -> ID a
- data RowID
- invalidRowId :: RowID
- isInvalidRowId :: RowID -> Bool
- fromRowId :: RowID -> Int
- toRowId :: Int -> RowID
- (.==) :: (Same s t, SqlType a) => Col s a -> Col t a -> Col s Bool
- (./=) :: (Same s t, SqlType a) => Col s a -> Col t a -> Col s Bool
- (.>) :: (Same s t, SqlOrd a) => Col s a -> Col t a -> Col s Bool
- (.<) :: (Same s t, SqlOrd a) => Col s a -> Col t a -> Col s Bool
- (.>=) :: (Same s t, SqlOrd a) => Col s a -> Col t a -> Col s Bool
- (.<=) :: (Same s t, SqlOrd a) => Col s a -> Col t a -> Col s Bool
- like :: Same s t => Col s Text -> Col t Text -> Col s Bool
- (.&&) :: Same s t => Col s Bool -> Col t Bool -> Col s Bool
- (.||) :: Same s t => Col s Bool -> Col t Bool -> Col s Bool
- not_ :: Col s Bool -> Col s Bool
- literal :: SqlType a => a -> Col s a
- is :: forall r s c. SqlType c => Selector r c -> c -> Row s r -> Col s Bool
- int :: Int -> Col s Int
- float :: Double -> Col s Double
- text :: Text -> Col s Text
- true :: Col s Bool
- false :: Col s Bool
- null_ :: SqlType a => Col s (Maybe a)
- roundTo :: Col s Int -> Col s Double -> Col s Double
- length_ :: Col s Text -> Col s Int
- isNull :: SqlType a => Col s (Maybe a) -> Col s Bool
- ifThenElse :: (Same s t, Same t u, SqlType a) => Col s Bool -> Col t a -> Col u a -> Col s a
- ifNull :: (Same s t, SqlType a) => Col s a -> Col t (Maybe a) -> Col s a
- matchNull :: (SqlType a, SqlType b, Same s t) => Col s b -> (Col s a -> Col s b) -> Col t (Maybe a) -> Col s b
- new :: forall s a. Relational a => [Assignment s a] -> Row s a
- only :: SqlType a => Col s a -> Row s (Only a)
- class Mappable f where
- round_ :: forall s a. (SqlType a, Num a) => Col s Double -> Col s a
- just :: SqlType a => Col s a -> Col s (Maybe a)
- fromBool :: (SqlType a, Num a) => Col s Bool -> Col s a
- fromInt :: (SqlType a, Num a) => Col s Int -> Col s a
- toString :: SqlType a => Col s a -> Col s Text
- data Aggr s a
- class Aggregates a
- type family OuterCols a where ...
- type family AggrCols a where ...
- type family LeftCols a where ...
- data Inner s
- class SqlType a => SqlOrd a
- innerJoin :: (Columns a, Columns (OuterCols a)) => (OuterCols a -> Col s Bool) -> Query (Inner s) a -> Query s (OuterCols a)
- leftJoin :: (Columns a, Columns (OuterCols a), Columns (LeftCols a)) => (OuterCols a -> Col s Bool) -> Query (Inner s) a -> Query s (LeftCols a)
- aggregate :: (Columns (AggrCols a), Aggregates a) => Query (Inner s) a -> Query s (AggrCols a)
- groupBy :: (Same s t, SqlType a) => Col (Inner s) a -> Query (Inner t) (Aggr (Inner t) a)
- count :: SqlType a => Col s a -> Aggr s Int
- avg :: (SqlType a, Num a) => Col s a -> Aggr s (Maybe a)
- sum_ :: forall a b s. (SqlType a, SqlType b, Num a, Num b) => Col s a -> Aggr s b
- max_ :: SqlOrd a => Col s a -> Aggr s (Maybe a)
- min_ :: SqlOrd a => Col s a -> Aggr s (Maybe a)
- insert :: (MonadSelda m, Relational a) => Table a -> [a] -> m Int
- insert_ :: (MonadSelda m, Relational a) => Table a -> [a] -> m ()
- insertWithPK :: (MonadSelda m, Relational a) => Table a -> [a] -> m (ID a)
- tryInsert :: (MonadSelda m, MonadCatch m, Relational a) => Table a -> [a] -> m Bool
- insertUnless :: (MonadSelda m, MonadMask m, Relational a) => Table a -> (Row (Backend m) a -> Col (Backend m) Bool) -> [a] -> m (Maybe (ID a))
- insertWhen :: (MonadSelda m, MonadMask m, Relational a) => Table a -> (Row (Backend m) a -> Col (Backend m) Bool) -> [a] -> m (Maybe (ID a))
- def :: SqlType a => a
- update :: (MonadSelda m, Relational a) => Table a -> (Row (Backend m) a -> Col (Backend m) Bool) -> (Row (Backend m) a -> Row (Backend m) a) -> m Int
- update_ :: (MonadSelda m, Relational a) => Table a -> (Row (Backend m) a -> Col (Backend m) Bool) -> (Row (Backend m) a -> Row (Backend m) a) -> m ()
- upsert :: (MonadSelda m, MonadMask m, Relational a) => Table a -> (Row (Backend m) a -> Col (Backend m) Bool) -> (Row (Backend m) a -> Row (Backend m) a) -> [a] -> m (Maybe (ID a))
- deleteFrom :: (MonadSelda m, Relational a) => Table a -> (Row (Backend m) a -> Col (Backend m) Bool) -> m Int
- deleteFrom_ :: (MonadSelda m, Relational a) => Table a -> (Row (Backend m) a -> Col (Backend m) Bool) -> m ()
- class Preparable q
- class Prepare q f
- prepared :: (Preparable q, Prepare q f, Equiv q f) => q -> f
- class Generic a
- data TableName
- data ColName
- data Attr a where
- (:-) :: SelectorLike g => g t a -> Attribute g t a -> Attr t
- data Attribute (g :: * -> * -> *) t c
- class ForeignKey a b where
- foreignKey :: Table t -> Selector t a -> Attribute Selector self b
- class SelectorLike g
- data Group t a where
- sel :: Selector t a -> Selector t a
- table :: forall a. Relational a => TableName -> [Attr a] -> Table a
- tableFieldMod :: forall a. Relational a => TableName -> [Attr a] -> (Text -> Text) -> Table a
- primary :: Attribute Group t a
- autoPrimary :: Attribute Selector t (ID t)
- weakAutoPrimary :: Attribute Selector t (ID t)
- untypedAutoPrimary :: Attribute Selector t RowID
- weakUntypedAutoPrimary :: Attribute Selector t RowID
- unique :: Attribute Group t a
- data IndexMethod
- index :: Attribute Group t c
- indexUsing :: IndexMethod -> Attribute Group t c
- createTable :: MonadSelda m => Table a -> m ()
- tryCreateTable :: MonadSelda m => Table a -> m ()
- dropTable :: MonadSelda m => Table a -> m ()
- tryDropTable :: MonadSelda m => Table a -> m ()
- class Tup a
- type family Head a where ...
- first :: Tup a => a -> Head a
- second :: Tup b => (a :*: b) -> Head b
- third :: Tup c => (a :*: (b :*: c)) -> Head c
- fourth :: Tup d => (a :*: (b :*: (c :*: d))) -> Head d
- fifth :: Tup e => (a :*: (b :*: (c :*: (d :*: e)))) -> Head e
- class Monad m => MonadIO (m :: Type -> Type)
- class MonadCatch m => MonadMask (m :: Type -> Type)
- liftIO :: MonadIO m => IO a -> m a
- data Text
- data Day
- data TimeOfDay
- data UTCTime
- data UUID
Running queries
class MonadIO m => MonadSelda m Source #
Some monad with Selda SQL capabilitites.
data SeldaError Source #
Thrown by any function in SeldaT
if an error occurs.
DbError String | Unable to open or connect to database. |
SqlError String | An error occurred while executing query. |
UnsafeError String | An error occurred due to improper use of an unsafe function. |
Instances
Eq SeldaError Source # | |
Defined in Database.Selda.Backend.Internal (==) :: SeldaError -> SeldaError -> Bool # (/=) :: SeldaError -> SeldaError -> Bool # | |
Show SeldaError Source # | |
Defined in Database.Selda.Backend.Internal showsPrec :: Int -> SeldaError -> ShowS # show :: SeldaError -> String # showList :: [SeldaError] -> ShowS # | |
Exception SeldaError Source # | |
Defined in Database.Selda.Backend.Internal toException :: SeldaError -> SomeException # fromException :: SomeException -> Maybe SeldaError # displayException :: SeldaError -> String # |
data ValidationError Source #
An error occurred when validating a database table. If this error is thrown, there is a bug in your database schema, and the particular table that triggered the error is unusable. Since validation is deterministic, this error will be thrown on every consecutive operation over the offending table.
Therefore, it is not meaningful to handle this exception in any way, just fix your bug instead.
Instances
Eq ValidationError Source # | |
Defined in Database.Selda.Table.Validation (==) :: ValidationError -> ValidationError -> Bool # (/=) :: ValidationError -> ValidationError -> Bool # | |
Show ValidationError Source # | |
Defined in Database.Selda.Table.Validation showsPrec :: Int -> ValidationError -> ShowS # show :: ValidationError -> String # showList :: [ValidationError] -> ShowS # | |
Exception ValidationError Source # | |
Defined in Database.Selda.Table.Validation |
Monad transformer adding Selda SQL capabilities.
Instances
type Relational a = (Generic a, SqlRow a, GRelation (Rep a)) Source #
Any type which has a corresponding relation.
To make a Relational
instance for some type, simply derive Generic
.
Note that only types which have a single data constructor, and where all
fields are instances of SqlValue
can be used with this module.
Attempting to use functions in this module with any type which doesn't
obey those constraints will result in a very confusing type error.
Wrapper for single column tables.
Use this when you need a table with only a single column, with table
or
selectValues
.
Only a |
Instances
A database table, based on some Haskell data type.
Any single constructor type can form the basis of a table, as long as
it derives Generic
and all of its fields are instances of SqlType
.
An SQL query.
A database row. A row is a collection of one or more columns.
A database column. A column is often a literal column table, but can also be an expression over such a column or a constant expression.
Instances
Mappable (Col :: Type -> Type -> Type) Source # | |
(SqlType a, Columns b) => Columns (Col s a :*: b) Source # | |
(SqlType a, Result b) => Result (Col s a :*: b) Source # | |
(SqlType a, Preparable b) => Preparable (Col s a -> b) Source # | |
Defined in Database.Selda.Prepared mkQuery :: MonadSelda m => Int -> (Col s a -> b) -> [SqlTypeRep] -> m CompResult | |
Fractional (Col s Int) Source # | |
Fractional (Col s Double) Source # | |
(SqlType a, Num a) => Num (Col s a) Source # | |
IsString (Col s Text) Source # | |
Defined in Database.Selda.Column fromString :: String -> Col s Text # | |
Columns (Col s a) Source # | |
SqlType a => Result (Col s a) Source # | |
type Container (Col :: Type -> Type -> Type) a Source # | |
class Typeable (Res r) => Result r Source #
An acceptable query result type; one or more columns stitched together
with :*:
.
toRes, finalCols
query :: (MonadSelda m, Result a) => Query (Backend m) a -> m [Res a] Source #
Run a query within a Selda monad. In practice, this is often a SeldaT
transformer on top of some other monad.
Selda transformers are entered using backend-specific withX
functions,
such as withSQLite
from the SQLite backend.
queryInto :: (MonadSelda m, Relational a) => Table a -> Query (Backend m) (Row (Backend m) a) -> m Int Source #
Perform the given query, and insert the result into the given table. Returns the number of inserted rows.
transaction :: (MonadSelda m, MonadMask m) => m a -> m a Source #
Perform the given computation atomically. If an exception is raised during its execution, the entire transaction will be rolled back and the exception re-thrown, even if the exception is caught and handled within the transaction.
withoutForeignKeyEnforcement :: (MonadSelda m, MonadMask m) => m a -> m a Source #
Run the given computation as a transaction without enforcing foreign key constraints.
If the computation finishes with the database in an inconsistent state with regards to foreign keys, the resulting behavior is undefined. Use with extreme caution, preferably only for migrations.
On the PostgreSQL backend, at least PostgreSQL 9.6 is required.
Using this should be avoided in favor of deferred foreign key constraints. See SQL backend documentation for deferred constraints.
newUuid :: MonadIO m => m UUID Source #
Generate a new random UUID using the system's random number generator. UUIDs generated this way are (astronomically likely to be) unique, but not necessarily unpredictable.
For applications where unpredictability is crucial, take care to use a proper cryptographic PRNG to generate your UUIDs.
Constructing queries
class Typeable a => SqlType a where Source #
Any datatype representable in (Selda's subset of) SQL.
Nothing
Create a literal of this type.
mkLit :: (Typeable a, SqlEnum a) => a -> Lit a Source #
Create a literal of this type.
sqlType :: Proxy a -> SqlTypeRep Source #
The SQL representation for this type.
fromSql :: SqlValue -> a Source #
Convert an SqlValue into this type.
fromSql :: (Typeable a, SqlEnum a) => SqlValue -> a Source #
Convert an SqlValue into this type.
defaultValue :: Lit a Source #
Default value when using def
at this type.
defaultValue :: (Typeable a, SqlEnum a) => Lit a Source #
Default value when using def
at this type.
Instances
SqlType Bool Source # | |
SqlType Double Source # | |
SqlType Int Source # | |
SqlType Ordering Source # | |
SqlType ByteString Source # | |
Defined in Database.Selda.SqlType mkLit :: ByteString -> Lit ByteString Source # sqlType :: Proxy ByteString -> SqlTypeRep Source # fromSql :: SqlValue -> ByteString Source # | |
SqlType ByteString Source # | |
Defined in Database.Selda.SqlType mkLit :: ByteString -> Lit ByteString Source # sqlType :: Proxy ByteString -> SqlTypeRep Source # fromSql :: SqlValue -> ByteString Source # | |
SqlType Text Source # | |
SqlType TimeOfDay Source # | |
SqlType UTCTime Source # | |
SqlType Day Source # | |
SqlType UUID Source # |
|
SqlType RowID Source # | |
SqlType a => SqlType (Maybe a) Source # | |
Typeable a => SqlType (ID a) Source # | |
((TypeError (((Text "'Only " :<>: ShowType a) :<>: Text "' is not a proper SQL type.") :$$: Text "Use 'the' to access the value of the column.") :: Constraint), Typeable a) => SqlType (Only a) Source # | |
class Typeable a => SqlRow a where Source #
Nothing
nextResult :: ResultReader a Source #
Read the next, potentially composite, result from a stream of columns.
nextResult :: (Generic a, GSqlRow (Rep a)) => ResultReader a Source #
Read the next, potentially composite, result from a stream of columns.
nestedCols :: Proxy a -> Int Source #
The number of nested columns contained in this type.
nestedCols :: (Generic a, GSqlRow (Rep a)) => Proxy a -> Int Source #
The number of nested columns contained in this type.
Instances
SqlRow a => SqlRow (Maybe a) Source # | |
Defined in Database.Selda.SqlRow nextResult :: ResultReader (Maybe a) Source # | |
SqlType a => SqlRow (Only a) Source # | |
Defined in Database.Selda nextResult :: ResultReader (Only a) Source # | |
(Typeable (a, b), GSqlRow (Rep (a, b))) => SqlRow (a, b) Source # | |
Defined in Database.Selda.SqlRow nextResult :: ResultReader (a, b) Source # nestedCols :: Proxy (a, b) -> Int Source # | |
(Typeable (a, b, c), GSqlRow (Rep (a, b, c))) => SqlRow (a, b, c) Source # | |
Defined in Database.Selda.SqlRow nextResult :: ResultReader (a, b, c) Source # nestedCols :: Proxy (a, b, c) -> Int Source # | |
(Typeable (a, b, c, d), GSqlRow (Rep (a, b, c, d))) => SqlRow (a, b, c, d) Source # | |
Defined in Database.Selda.SqlRow nextResult :: ResultReader (a, b, c, d) Source # nestedCols :: Proxy (a, b, c, d) -> Int Source # | |
(Typeable (a, b, c, d, e), GSqlRow (Rep (a, b, c, d, e))) => SqlRow (a, b, c, d, e) Source # | |
Defined in Database.Selda.SqlRow nextResult :: ResultReader (a, b, c, d, e) Source # nestedCols :: Proxy (a, b, c, d, e) -> Int Source # | |
(Typeable (a, b, c, d, e, f), GSqlRow (Rep (a, b, c, d, e, f))) => SqlRow (a, b, c, d, e, f) Source # | |
Defined in Database.Selda.SqlRow nextResult :: ResultReader (a, b, c, d, e, f) Source # nestedCols :: Proxy (a, b, c, d, e, f) -> Int Source # | |
(Typeable (a, b, c, d, e, f, g), GSqlRow (Rep (a, b, c, d, e, f, g))) => SqlRow (a, b, c, d, e, f, g) Source # | |
Defined in Database.Selda.SqlRow nextResult :: ResultReader (a, b, c, d, e, f, g) Source # nestedCols :: Proxy (a, b, c, d, e, f, g) -> Int Source # |
class (Typeable a, Bounded a, Enum a) => SqlEnum a where Source #
Any type that's bounded, enumerable and has a text representation, and thus representable as a Selda enumerable.
While it would be more efficient to store enumerables as integers, this makes hand-rolled SQL touching the values inscrutable, and will break if the user a) derives Enum and b) changes the order of their constructors. Long-term, this should be implemented in PostgreSQL as a proper enum anyway, which mostly renders the performance argument moot.
Any column tuple.
toTup, fromTup
class s ~ t => Same s t Source #
Denotes that scopes s
and t
are identical.
Instances
(s ~ t, (TypeError (Text "An identifier from an outer scope may not be used in an inner query.") :: Constraint)) => Same (s :: k) (t :: k) Source # | |
Defined in Database.Selda.Column | |
Same (s :: k) (s :: k) Source # | |
Defined in Database.Selda.Column |
The order in which to sort result rows.
data a :*: b where infixr 1 Source #
An inductively defined "tuple", or heterogeneous, non-empty list.
Instances
(Eq a, Eq b) => Eq (a :*: b) Source # | |
(Ord a, Ord b) => Ord (a :*: b) Source # | |
Defined in Database.Selda.Types | |
(Show a, Show b) => Show (a :*: b) Source # | |
Generic (a :*: b) Source # | |
Tup (a :*: b) Source # | |
Defined in Database.Selda.Types | |
(SqlRow a, Columns b) => Columns (Row s a :*: b) Source # | |
(SqlType a, Columns b) => Columns (Col s a :*: b) Source # | |
Aggregates b => Aggregates (Aggr (Inner s) a :*: b) Source # | |
Defined in Database.Selda.Inner | |
(SqlRow a, Result b) => Result (Row s a :*: b) Source # | |
(SqlType a, Result b) => Result (Col s a :*: b) Source # | |
type Rep (a :*: b) Source # | |
Defined in Database.Selda.Types type Rep (a :*: b) = D1 (MetaData ":*:" "Database.Selda.Types" "selda-0.5.1.0-AKzjAihhRTX3ZzXNm1yjsq" False) (C1 (MetaCons ":*:" (InfixI RightAssociative 1) False) (S1 (MetaSel (Nothing :: Maybe Symbol) NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 a) :*: S1 (MetaSel (Nothing :: Maybe Symbol) NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 b))) |
selectValues :: forall s a. Relational a => [a] -> Query s (Row s a) Source #
Query an ad hoc table of type a
. Each element in the given list represents
one row in the ad hoc table.
from :: (Typeable t, SqlType a) => Selector t a -> Query s (Row s t) -> Query s (Col s a) infixr 7 Source #
Convenient shorthand for fmap (! sel) q
.
The following two queries are quivalent:
q1 = name `from` select people q2 = do person <- select people return (person ! name)
distinct :: (Columns a, Columns (OuterCols a)) => Query (Inner s) a -> Query s (OuterCols a) Source #
Remove all duplicates from the result set.
restrict :: Same s t => Col s Bool -> Query t () Source #
Restrict the query somehow. Roughly equivalent to WHERE
.
limit :: Same s t => Int -> Int -> Query (Inner s) a -> Query t (OuterCols a) Source #
Drop the first m
rows, then get at most n
of the remaining rows from the
given subquery.
order :: (Same s t, SqlType a) => Col s a -> Order -> Query t () Source #
Sort the result rows in ascending or descending order on the given row.
If multiple order
directives are given, later directives are given
precedence but do not cancel out earlier ordering directives.
To get a list of persons sorted primarily on age and secondarily on name:
peopleInAgeAndNameOrder = do person <- select people order (person ! name) ascending order (person ! age) ascending return (person ! name)
For a table [(Alice, 20), (Bob, 20), (Eve, 18)]
, this query
will always return [Eve, Alice, Bob]
.
The reason for later orderings taking precedence and not the other way
around is composability: order
should always sort the current
result set to avoid weird surprises when a previous order
directive
is buried somewhere deep in an earlier query.
However, the ordering must always be stable, to ensure that previous
calls to order are not simply erased.
descending :: Order Source #
Ordering for order
.
orderRandom :: Query s () Source #
Sort the result rows in random order.
inner :: (Columns a, Columns (OuterCols a)) => Query (Inner s) a -> Query s (OuterCols a) Source #
Explicitly create an inner query. Equivalent to innerJoin (const true)
.
Sometimes it's handy, for performance reasons and otherwise, to perform a subquery and restrict only that query before adding the result of the query to the result set, instead of first adding the query to the result set and restricting the whole result set afterwards.
suchThat :: (Columns a, Columns (OuterCols a)) => Query (Inner s) a -> (a -> Col (Inner s) Bool) -> Query s (OuterCols a) infixr 7 Source #
Create and filter an inner query, before adding it to the current result set.
q
is generally more efficient than
suchThat
pselect q >>= x -> restrict (p x) >> pure x
.
Working with selectors
A column selector. Column selectors can be used together with the !
and
with
functions to get and set values on rows, or to specify
foreign keys.
Instances
SelectorLike Selector Source # | |
Defined in Database.Selda.Table | |
(Relational t, HasField name t, FieldType name t ~ a) => IsLabel name (Selector t a) Source # | |
Defined in Database.Selda.FieldSelectors |
type family Coalesce a where ... Source #
Coalesce nested nullable column into a single level of nesting.
class (Relational t, SqlType (FieldType name t), GRSel name (Rep t), NonError (FieldType name t)) => HasField (name :: Symbol) t Source #
Any table type t
, which has a field named name
.
Instances
(Relational t, SqlType (FieldType name t), GRSel name (Rep t), NonError (FieldType name t)) => HasField name t Source # | |
Defined in Database.Selda.FieldSelectors |
type FieldType name t = GFieldType (Rep t) (NoSuchSelector t name) name Source #
The type of the name
field, in the record type t
.
(!) :: SqlType a => Row s t -> Selector t a -> Col s a infixl 9 Source #
Extract the given column from the given row.
(?) :: SqlType a => Row s (Maybe t) -> Selector t a -> Col s (Coalesce (Maybe a)) infixl 9 Source #
Extract the given column from the given nullable row.
Nullable rows usually result from left joins.
If a nullable column is extracted from a nullable row, the resulting
nested Maybe
s will be squashed into a single level of nesting.
data Assignment s a where Source #
A selector-value assignment pair.
(:=) :: Selector t a -> Col s a -> Assignment s t infixl 2 | Set the given column to the given value. |
with :: Row s a -> [Assignment s a] -> Row s a Source #
For each selector-value pair in the given list, on the given tuple, update the field pointed out by the selector with the corresponding value.
(+=) :: (SqlType a, Num (Col s a)) => Selector t a -> Col s a -> Assignment s t infixl 2 Source #
Add the given column to the column pointed to by the given selector.
(-=) :: (SqlType a, Num (Col s a)) => Selector t a -> Col s a -> Assignment s t infixl 2 Source #
Subtract the given column from the column pointed to by the given selector.
(*=) :: (SqlType a, Num (Col s a)) => Selector t a -> Col s a -> Assignment s t infixl 2 Source #
Multiply the column pointed to by the given selector, by the given column.
(||=) :: Selector t Bool -> Col s Bool -> Assignment s t infixl 2 Source #
Logically OR
the column pointed to by the given selector with
the given column.
(&&=) :: Selector t Bool -> Col s Bool -> Assignment s t infixl 2 Source #
Logically AND
the column pointed to by the given selector with
the given column.
($=) :: Selector t a -> (Col s a -> Col s a) -> Assignment s t infixl 2 Source #
Apply the given function to the given column.
Expressions over columns
Any container type for which we can check object membership.
A typed row identifier.
Generic tables should use this instead of RowID
.
Use untyped
to erase the type of a row identifier, and cast
from the
Database.Selda.Unsafe module if you for some reason need to add a type
to a row identifier.
A typed row identifier which is guaranteed to not match any row in any table.
isInvalidId :: ID a -> Bool Source #
Is the given typed row identifier invalid? I.e. is it guaranteed to not match any row in any table?
fromId :: ID a -> Int Source #
Create a typed row identifier from an integer. Use with caution, preferably only when reading user input.
Create a typed row identifier from an integer. Use with caution, preferably only when reading user input.
A row identifier for some table. This is the type of auto-incrementing primary keys.
invalidRowId :: RowID Source #
A row identifier which is guaranteed to not match any row in any table.
isInvalidRowId :: RowID -> Bool Source #
Is the given row identifier invalid? I.e. is it guaranteed to not match any row in any table?
toRowId :: Int -> RowID Source #
Create a row identifier from an integer. Use with caution, preferably only when reading user input.
(.==) :: (Same s t, SqlType a) => Col s a -> Col t a -> Col s Bool infixl 4 Source #
Comparisons over columns.
Note that when comparing nullable (i.e. Maybe
) columns, SQL NULL
semantics are used. This means that comparing to a NULL
field will remove
the row in question from the current set.
To test for NULL
, use isNull
instead of .== literal Nothing
.
(./=) :: (Same s t, SqlType a) => Col s a -> Col t a -> Col s Bool infixl 4 Source #
Comparisons over columns.
Note that when comparing nullable (i.e. Maybe
) columns, SQL NULL
semantics are used. This means that comparing to a NULL
field will remove
the row in question from the current set.
To test for NULL
, use isNull
instead of .== literal Nothing
.
like :: Same s t => Col s Text -> Col t Text -> Col s Bool infixl 4 Source #
The SQL LIKE
operator; matches strings with %
wildcards.
For instance:
"%gon" `like` "dragon" .== true
is :: forall r s c. SqlType c => Selector r c -> c -> Row s r -> Col s Bool Source #
Returns true
if the given field in the given row is equal to the given
literal.
roundTo :: Col s Int -> Col s Double -> Col s Double Source #
Round a column to the given number of decimals places.
ifThenElse :: (Same s t, Same t u, SqlType a) => Col s Bool -> Col t a -> Col u a -> Col s a Source #
Perform a conditional on a column
ifNull :: (Same s t, SqlType a) => Col s a -> Col t (Maybe a) -> Col s a Source #
If the second value is Nothing, return the first value. Otherwise return the second value.
matchNull :: (SqlType a, SqlType b, Same s t) => Col s b -> (Col s a -> Col s b) -> Col t (Maybe a) -> Col s b Source #
Applies the given function to the given nullable column where it isn't null, and returns the given default value where it is.
This is the Selda equivalent of maybe
.
new :: forall s a. Relational a => [Assignment s a] -> Row s a Source #
Create a new column with the given fields. Any unassigned fields will contain their default values.
only :: SqlType a => Col s a -> Row s (Only a) Source #
Create a singleton table column from an appropriate value.
class Mappable f where Source #
Any container type which can be mapped over.
Sort of like Functor
, if you squint a bit.
(.<$>) :: (SqlType a, SqlType b) => (Col s a -> Col s b) -> f s (Container f a) -> f s (Container f b) infixl 4 Source #
Converting between column types
round_ :: forall s a. (SqlType a, Num a) => Col s Double -> Col s a Source #
Round a value to the nearest integer. Equivalent to roundTo 0
.
just :: SqlType a => Col s a -> Col s (Maybe a) Source #
Lift a non-nullable column to a nullable one. Useful for creating expressions over optional columns:
data Person = Person {name :: Text, age :: Int, pet :: Maybe Text} deriving Generic instance SqlRow Person people :: Table Person people = table "people" [] peopleWithCats = do person <- select people restrict (person ! #pet .== just "cat") return (person ! #name)
fromBool :: (SqlType a, Num a) => Col s Bool -> Col s a Source #
Convert a boolean column to any numeric type.
fromInt :: (SqlType a, Num a) => Col s Int -> Col s a Source #
Convert an integer column to any numeric type.
Inner queries
A single aggregate column.
Aggregate columns may not be used to restrict queries.
When returned from an aggregate
subquery, an aggregate column is
converted into a non-aggregate column.
Instances
Mappable Aggr Source # | |
Aggregates b => Aggregates (Aggr (Inner s) a :*: b) Source # | |
Defined in Database.Selda.Inner | |
Aggregates (Aggr (Inner s) a) Source # | |
Defined in Database.Selda.Inner | |
type Container Aggr a Source # | |
Defined in Database.Selda |
class Aggregates a Source #
One or more aggregate columns.
unAggrs
Instances
Aggregates b => Aggregates (Aggr (Inner s) a :*: b) Source # | |
Defined in Database.Selda.Inner | |
Aggregates (Aggr (Inner s) a) Source # | |
Defined in Database.Selda.Inner |
type family OuterCols a where ... Source #
Convert one or more inner column to equivalent columns in the outer query.
OuterCols (Aggr (Inner s) a :*: Aggr (Inner s) b) = Col s a :*: Col s b
,
for instance.
OuterCols (Col (Inner s) a :*: b) = Col s a :*: OuterCols b | |
OuterCols (Col (Inner s) a) = Col s a | |
OuterCols (Row (Inner s) a :*: b) = Row s a :*: OuterCols b | |
OuterCols (Row (Inner s) a) = Row s a | |
OuterCols (Col s a) = TypeError (Text "An inner query can only return rows and columns from its own scope.") | |
OuterCols (Row s a) = TypeError (Text "An inner query can only return rows and columns from its own scope.") | |
OuterCols a = TypeError (Text "Only (inductive tuples of) row and columns can be returned from" :$$: Text "an inner query.") |
type family AggrCols a where ... Source #
AggrCols (Aggr (Inner s) a :*: b) = Col s a :*: AggrCols b | |
AggrCols (Aggr (Inner s) a) = Col s a | |
AggrCols (Aggr s a) = TypeError (Text "An aggregate query can only return columns from its own" :$$: Text "scope.") | |
AggrCols a = TypeError (Text "Only (inductive tuples of) aggregates can be returned from" :$$: Text "an aggregate query.") |
type family LeftCols a where ... Source #
The results of a left join are always nullable, as there is no guarantee
that all joined columns will be non-null.
JoinCols a
where a
is an extensible tuple is that same tuple, but in
the outer query and with all elements nullable.
For instance:
LeftCols (Col (Inner s) Int :*: Col (Inner s) Text) = Col s (Maybe Int) :*: Col s (Maybe Text)
LeftCols (Col (Inner s) (Maybe a) :*: b) = Col s (Maybe a) :*: LeftCols b | |
LeftCols (Col (Inner s) a :*: b) = Col s (Maybe a) :*: LeftCols b | |
LeftCols (Col (Inner s) (Maybe a)) = Col s (Maybe a) | |
LeftCols (Col (Inner s) a) = Col s (Maybe a) | |
LeftCols (Row (Inner s) (Maybe a) :*: b) = Row s (Maybe a) :*: LeftCols b | |
LeftCols (Row (Inner s) a :*: b) = Row s (Maybe a) :*: LeftCols b | |
LeftCols (Row (Inner s) (Maybe a)) = Row s (Maybe a) | |
LeftCols (Row (Inner s) a) = Row s (Maybe a) | |
LeftCols a = TypeError (Text "Only (inductive tuples of) rows and columns can be returned" :$$: Text "from a join.") |
Denotes an inner query.
For aggregation, treating sequencing as the cartesian product of queries
does not work well.
Instead, we treat the sequencing of aggregate
with other
queries as the cartesian product of the aggregated result of the query,
a small but important difference.
However, for this to work, the aggregate query must not depend on any
columns in the outer product. Therefore, we let the aggregate query be
parameterized over Inner s
if the parent query is parameterized over s
,
to enforce this separation.
Instances
Aggregates b => Aggregates (Aggr (Inner s) a :*: b) Source # | |
Defined in Database.Selda.Inner | |
Aggregates (Aggr (Inner s) a) Source # | |
Defined in Database.Selda.Inner |
class SqlType a => SqlOrd a Source #
Instances
(SqlType a, Num a) => SqlOrd a Source # | |
Defined in Database.Selda | |
SqlOrd Text Source # | |
Defined in Database.Selda | |
SqlOrd TimeOfDay Source # | |
Defined in Database.Selda | |
SqlOrd UTCTime Source # | |
Defined in Database.Selda | |
SqlOrd Day Source # | |
Defined in Database.Selda | |
SqlOrd RowID Source # | |
Defined in Database.Selda | |
SqlOrd a => SqlOrd (Maybe a) Source # | |
Defined in Database.Selda | |
Typeable a => SqlOrd (ID a) Source # | |
Defined in Database.Selda |
:: (Columns a, Columns (OuterCols a)) | |
=> (OuterCols a -> Col s Bool) | Predicate determining which lines to join. | Right-hand query to join. |
-> Query (Inner s) a | |
-> Query s (OuterCols a) |
Perform an INNER JOIN
with the current result set and the given query.
:: (Columns a, Columns (OuterCols a), Columns (LeftCols a)) | |
=> (OuterCols a -> Col s Bool) | Predicate determining which lines to join. | Right-hand query to join. |
-> Query (Inner s) a | |
-> Query s (LeftCols a) |
Perform a LEFT JOIN
with the current result set (i.e. the outer query)
as the left hand side, and the given query as the right hand side.
Like with aggregate
, the inner (or right) query must not depend on the
outer (or right) one.
The given predicate over the values returned by the inner query determines for each row whether to join or not. This predicate may depend on any values from the outer query.
For instance, the following will list everyone in the people
table
together with their address if they have one; if they don't, the address
field will be NULL
.
getAddresses :: Query s (Col s Text :*: Col s (Maybe Text)) getAddresses = do (name :*: _) <- select people (_ :*: address) <- leftJoin (\(n :*: _) -> n .== name) (select addresses) return (name :*: address)
aggregate :: (Columns (AggrCols a), Aggregates a) => Query (Inner s) a -> Query s (AggrCols a) Source #
Execute a query, returning an aggregation of its results.
The query must return an inductive tuple of Aggregate
columns.
When aggregate
returns, those columns are converted into non-aggregate
columns, which may then be used to further restrict the query.
Note that aggregate queries must not depend on outer queries, nor must they return any non-aggregate columns. Attempting to do either results in a type error.
The SQL HAVING
keyword can be implemented by combining aggregate
and restrict
:
-- Find the number of people living on every address, for all addresses -- with more than one tenant: -- SELECT COUNT(name) AS c, address FROM housing GROUP BY name HAVING c > 1 numPpl = do (num_tenants :*: theAddress) <- aggregate $ do h <- select housing theAddress <- groupBy (h ! address) return (count (h ! address) :*: theAddress) restrict (num_tenants .> 1) return (num_tenants :*: theAddress)
groupBy :: (Same s t, SqlType a) => Col (Inner s) a -> Query (Inner t) (Aggr (Inner t) a) Source #
Group an aggregate query by a column. Attempting to group a non-aggregate query is a type error. An aggregate representing the grouped-by column is returned, which can be returned from the aggregate query. For instance, if you want to find out how many people have a pet at home:
aggregate $ do person <- select people name' <- groupBy (person ! name) return (name' :*: count(person ! pet_name) .> 0)
count :: SqlType a => Col s a -> Aggr s Int Source #
The number of non-null values in the given column.
avg :: (SqlType a, Num a) => Col s a -> Aggr s (Maybe a) Source #
The average of all values in the given column.
sum_ :: forall a b s. (SqlType a, SqlType b, Num a, Num b) => Col s a -> Aggr s b Source #
Sum all values in the given column.
max_ :: SqlOrd a => Col s a -> Aggr s (Maybe a) Source #
The greatest value in the given column. Texts are compared lexically.
min_ :: SqlOrd a => Col s a -> Aggr s (Maybe a) Source #
The smallest value in the given column. Texts are compared lexically.
Modifying tables
insert :: (MonadSelda m, Relational a) => Table a -> [a] -> m Int Source #
Insert the given values into the given table. All columns of the table
must be present. If your table has an auto-incrementing primary key,
use the special value def
for that column to get the auto-incrementing
behavior.
Returns the number of rows that were inserted.
To insert a list of tuples into a table with auto-incrementing primary key:
data Person = Person { id :: ID Person , name :: Text , age :: Int , pet :: Maybe Text } deriving Generic instance SqlResult Person people :: Table Person people = table "people" [autoPrimary :- id] main = withSQLite "my_database.sqlite" $ do insert_ people [ Person def "Link" 125 (Just "horse") , Person def "Zelda" 119 Nothing , ... ]
Note that if one or more of the inserted rows would cause a constraint violation, NO rows will be inserted; the whole insertion fails atomically.
insert_ :: (MonadSelda m, Relational a) => Table a -> [a] -> m () Source #
Like insert
, but does not return anything.
Use this when you really don't care about how many rows were inserted.
insertWithPK :: (MonadSelda m, Relational a) => Table a -> [a] -> m (ID a) Source #
Like insert
, but returns the primary key of the last inserted row.
Attempting to run this operation on a table without an auto-incrementing
primary key will always return a row identifier that is guaranteed to not
match any row in any table.
tryInsert :: (MonadSelda m, MonadCatch m, Relational a) => Table a -> [a] -> m Bool Source #
Attempt to insert a list of rows into a table, but don't raise an error
if the insertion fails. Returns True
if the insertion succeeded, otherwise
False
.
Like insert
, if even one of the inserted rows would cause a constraint
violation, the whole insert operation fails.
insertUnless :: (MonadSelda m, MonadMask m, Relational a) => Table a -> (Row (Backend m) a -> Col (Backend m) Bool) -> [a] -> m (Maybe (ID a)) Source #
Perform the given insert, if no rows already present in the table match
the given predicate.
Returns the primary key of the last inserted row,
if the insert was performed.
If called on a table which doesn't have an auto-incrementing primary key,
Just id
is always returned on successful insert, where id
is a row
identifier guaranteed to not match any row in any table.
insertWhen :: (MonadSelda m, MonadMask m, Relational a) => Table a -> (Row (Backend m) a -> Col (Backend m) Bool) -> [a] -> m (Maybe (ID a)) Source #
Like insertUnless
, but performs the insert when at least one row matches
the predicate.
def :: SqlType a => a Source #
The default value for a column during insertion. For an auto-incrementing primary key, the default value is the next key.
Using def
in any other context than insertion results in a runtime error.
:: (MonadSelda m, Relational a) | |
=> Table a | Table to update. |
-> (Row (Backend m) a -> Col (Backend m) Bool) | Predicate. |
-> (Row (Backend m) a -> Row (Backend m) a) | Update function. |
-> m Int |
Update the given table using the given update function, for all rows matching the given predicate. Returns the number of updated rows.
update_ :: (MonadSelda m, Relational a) => Table a -> (Row (Backend m) a -> Col (Backend m) Bool) -> (Row (Backend m) a -> Row (Backend m) a) -> m () Source #
Like update
, but doesn't return the number of updated rows.
upsert :: (MonadSelda m, MonadMask m, Relational a) => Table a -> (Row (Backend m) a -> Col (Backend m) Bool) -> (Row (Backend m) a -> Row (Backend m) a) -> [a] -> m (Maybe (ID a)) Source #
Attempt to perform the given update. If no rows were updated, insert the
given row.
Returns the primary key of the inserted row, if the insert was performed.
Calling this function on a table which does not have a primary key will
return Just id
on a successful insert, where id
is a row identifier
guaranteed to not match any row in any table.
Note that this may perform two separate queries: one update, potentially followed by one insert.
deleteFrom :: (MonadSelda m, Relational a) => Table a -> (Row (Backend m) a -> Col (Backend m) Bool) -> m Int Source #
From the given table, delete all rows matching the given predicate. Returns the number of deleted rows.
deleteFrom_ :: (MonadSelda m, Relational a) => Table a -> (Row (Backend m) a -> Col (Backend m) Bool) -> m () Source #
Like deleteFrom
, but does not return the number of deleted rows.
Prepared statements
class Preparable q Source #
mkQuery
Instances
(SqlType a, Preparable b) => Preparable (Col s a -> b) Source # | |
Defined in Database.Selda.Prepared mkQuery :: MonadSelda m => Int -> (Col s a -> b) -> [SqlTypeRep] -> m CompResult | |
Result a => Preparable (Query s a) Source # | |
Defined in Database.Selda.Prepared mkQuery :: MonadSelda m => Int -> Query s a -> [SqlTypeRep] -> m CompResult |
Some parameterized query q
that can be prepared into a function f
in some MonadSelda
.
mkFun
prepared :: (Preparable q, Prepare q f, Equiv q f) => q -> f Source #
Create a prepared Selda function. A prepared function has zero or more arguments, and will get compiled into a prepared statement by the first backend to execute it. Any subsequent calls to the function for the duration of the connection to the database will reuse the prepared statement.
Preparable functions are of the form
(SqlType a, SqlType b, ...) => Col s a -> Col s b -> ... -> Query s r
.
The resulting prepared function will be of the form
MonadSelda m => a -> b -> ... -> m [Res r]
.
Note, however, that when using prepared
, you must give a concrete type
for m
due to how Haskell's type class resolution works.
Prepared functions rely on memoization for just-in-time preparation and
caching. This means that if GHC accidentally inlines your prepared function,
it may get prepared twice.
While this does not affect the correctness of your program, and is
fairly unlikely to happen, if you want to be absolutely sure that your
queries aren't re-prepared more than absolutely necessary,
consider adding a NOINLINE
annotation to each prepared function.
Note that when using a constrained backend type variable (i.e.
foo :: Bar b => SeldaM b [Int]
), optimizations must be enabled for
prepared statements to be effective.
A usage example:
persons :: Table (Text, Int) (persons, name :*: age) = tableWithSelectors "ages" [name :- primary] {-# NOINLINE ageOf #-} ageOf :: Text -> SeldaM [Int] ageOf = prepared $ \n -> do person <- select ages restrict $ (person!name .== n) return age
Defining schemas
Representable types of kind *
.
This class is derivable in GHC with the DeriveGeneric
flag on.
A Generic
instance must satisfy the following laws:
from
.to
≡id
to
.from
≡id
Instances
Name of a database table.
Name of a database column.
A generic column attribute.
Essentially a pair or a record selector over the type a
and a column
attribute. An attribute may be either a Group
attribute, meaning that
it can span multiple columns, or a Selector
-- single column -- attribute.
(:-) :: SelectorLike g => g t a -> Attribute g t a -> Attr t infixl 0 |
data Attribute (g :: * -> * -> *) t c Source #
Some attribute that may be set on a column of type c
, in a table of
type t
.
class ForeignKey a b where Source #
foreignKey :: Table t -> Selector t a -> Attribute Selector self b Source #
A foreign key constraint referencing the given table and column.
Instances
ForeignKey a a Source # | |
Defined in Database.Selda.Table | |
ForeignKey a (Maybe a) Source # | |
Defined in Database.Selda.Table | |
ForeignKey (Maybe a) a Source # | |
Defined in Database.Selda.Table |
class SelectorLike g Source #
indices
Instances
SelectorLike Selector Source # | |
Defined in Database.Selda.Table | |
SelectorLike Group Source # | |
Defined in Database.Selda.Table |
A non-empty list of selectors, where the element selectors need not have the same type. Used to specify constraints, such as uniqueness or primary key, potentially spanning multiple columns.
sel :: Selector t a -> Selector t a Source #
Annotation to force the type of a polymorphic label (i.e. #foo
) to
be a selector. This is useful, for instance, when defining unique
constraints: sel #foo :- unique
.
table :: forall a. Relational a => TableName -> [Attr a] -> Table a Source #
Generate a table from the given table name and list of column attributes.
All Maybe
fields in the table's type will be represented by nullable
columns, and all non-Maybe
fields fill be represented by required
columns.
For example:
data Person = Person { id :: ID Person , name :: Text , age :: Int , pet :: Maybe Text } deriving Generic people :: Table Person people = table "people" [#id :- autoPrimary]
This will result in a table of Person
s, with an auto-incrementing primary
key.
If the given type does not have record selectors, the column names will be
col_1
, col_2
, etc.
tableFieldMod :: forall a. Relational a => TableName -> [Attr a] -> (Text -> Text) -> Table a Source #
Generate a table from the given table name, a list of column attributes and a function that maps from field names to column names. Ex.:
data Person = Person { personId :: Int , personName :: Text , personAge :: Int , personPet :: Maybe Text } deriving Generic people :: Table Person people = tableFieldMod "people" [#personName :- autoPrimaryGen] (fromJust . stripPrefix "person")
This will create a table with the columns named
Id
, Name
, Age
and Pet
.
weakAutoPrimary :: Attribute Selector t (ID t) Source #
A "weakly auto-incrementing" primary key.
Behaves like autoPrimary
, but the sequence of generated keys is not
guaranteed to be monotonically increasing.
This gives better performance on some backends, but means that
the relation a > b = a was inserted at a later point in time than b
does not hold.
untypedAutoPrimary :: Attribute Selector t RowID Source #
An untyped auto-incrementing primary key. You should really only use this for ad hoc tables, such as tuples.
weakUntypedAutoPrimary :: Attribute Selector t RowID Source #
Like weakAutoPrimary
, but for untyped IDs.
data IndexMethod Source #
Method to use for indexing with indexedUsing
.
Index methods are ignored by the SQLite backend, as SQLite doesn't support
different index methods.
Instances
Eq IndexMethod Source # | |
Defined in Database.Selda.Table.Type (==) :: IndexMethod -> IndexMethod -> Bool # (/=) :: IndexMethod -> IndexMethod -> Bool # | |
Ord IndexMethod Source # | |
Defined in Database.Selda.Table.Type compare :: IndexMethod -> IndexMethod -> Ordering # (<) :: IndexMethod -> IndexMethod -> Bool # (<=) :: IndexMethod -> IndexMethod -> Bool # (>) :: IndexMethod -> IndexMethod -> Bool # (>=) :: IndexMethod -> IndexMethod -> Bool # max :: IndexMethod -> IndexMethod -> IndexMethod # min :: IndexMethod -> IndexMethod -> IndexMethod # | |
Show IndexMethod Source # | |
Defined in Database.Selda.Table.Type showsPrec :: Int -> IndexMethod -> ShowS # show :: IndexMethod -> String # showList :: [IndexMethod] -> ShowS # |
indexUsing :: IndexMethod -> Attribute Group t c Source #
Create an index using the given index method on this column.
Creating and dropping tables
createTable :: MonadSelda m => Table a -> m () Source #
Create a table from the given schema.
tryCreateTable :: MonadSelda m => Table a -> m () Source #
Create a table from the given schema, unless it already exists.
dropTable :: MonadSelda m => Table a -> m () Source #
Drop the given table.
tryDropTable :: MonadSelda m => Table a -> m () Source #
Drop the given table, if it exists.
Tuple convenience functions
tupHead
fourth :: Tup d => (a :*: (b :*: (c :*: d))) -> Head d Source #
Get the fourth element of an inductive tuple.
fifth :: Tup e => (a :*: (b :*: (c :*: (d :*: e)))) -> Head e Source #
Get the fifth element of an inductive tuple.
Useful re-exports
class Monad m => MonadIO (m :: Type -> Type) #
Monads in which IO
computations may be embedded.
Any monad built by applying a sequence of monad transformers to the
IO
monad will be an instance of this class.
Instances should satisfy the following laws, which state that liftIO
is a transformer of monads:
Instances
class MonadCatch m => MonadMask (m :: Type -> Type) #
A class for monads which provide for the ability to account for all possible exit points from a computation, and to mask asynchronous exceptions. Continuation-based monads are invalid instances of this class.
Instances should ensure that, in the following code:
fg = f `finally` g
The action g
is called regardless of what occurs within f
, including
async exceptions. Some monads allow f
to abort the computation via other
effects than throwing an exception. For simplicity, we will consider aborting
and throwing an exception to be two forms of "throwing an error".
If f
and g
both throw an error, the error thrown by fg
depends on which
errors we're talking about. In a monad transformer stack, the deeper layers
override the effects of the inner layers; for example, ExceptT e1 (Except
e2) a
represents a value of type Either e2 (Either e1 a)
, so throwing both
an e1
and an e2
will result in Left e2
. If f
and g
both throw an
error from the same layer, instances should ensure that the error from g
wins.
Effects other than throwing an error are also overriden by the deeper layers.
For example, StateT s Maybe a
represents a value of type s -> Maybe (a,
s)
, so if an error thrown from f
causes this function to return Nothing
,
any changes to the state which f
also performed will be erased. As a
result, g
will see the state as it was before f
. Once g
completes,
f
's error will be rethrown, so g
' state changes will be erased as well.
This is the normal interaction between effects in a monad transformer stack.
By contrast, lifted-base's
version of finally
always discards all of g
's non-IO effects, and g
never sees any of f
's non-IO effects, regardless of the layer ordering and
regardless of whether f
throws an error. This is not the result of
interacting effects, but a consequence of MonadBaseControl
's approach.
Instances
MonadMask IO | |
e ~ SomeException => MonadMask (Either e) | Since: exceptions-0.8.3 |
Defined in Control.Monad.Catch | |
MonadMask m => MonadMask (MaybeT m) | Since: exceptions-0.10.0 |
Defined in Control.Monad.Catch | |
MonadMask m => MonadMask (ExceptT e m) | Since: exceptions-0.9.0 |
Defined in Control.Monad.Catch mask :: ((forall a. ExceptT e m a -> ExceptT e m a) -> ExceptT e m b) -> ExceptT e m b # uninterruptibleMask :: ((forall a. ExceptT e m a -> ExceptT e m a) -> ExceptT e m b) -> ExceptT e m b # generalBracket :: ExceptT e m a -> (a -> ExitCase b -> ExceptT e m c) -> (a -> ExceptT e m b) -> ExceptT e m (b, c) # | |
MonadMask m => MonadMask (IdentityT m) | |
Defined in Control.Monad.Catch mask :: ((forall a. IdentityT m a -> IdentityT m a) -> IdentityT m b) -> IdentityT m b # uninterruptibleMask :: ((forall a. IdentityT m a -> IdentityT m a) -> IdentityT m b) -> IdentityT m b # generalBracket :: IdentityT m a -> (a -> ExitCase b -> IdentityT m c) -> (a -> IdentityT m b) -> IdentityT m (b, c) # | |
(Error e, MonadMask m) => MonadMask (ErrorT e m) | |
Defined in Control.Monad.Catch | |
MonadMask m => MonadMask (StateT s m) | |
Defined in Control.Monad.Catch | |
MonadMask m => MonadMask (StateT s m) | |
Defined in Control.Monad.Catch | |
(MonadMask m, Monoid w) => MonadMask (WriterT w m) | |
Defined in Control.Monad.Catch mask :: ((forall a. WriterT w m a -> WriterT w m a) -> WriterT w m b) -> WriterT w m b # uninterruptibleMask :: ((forall a. WriterT w m a -> WriterT w m a) -> WriterT w m b) -> WriterT w m b # generalBracket :: WriterT w m a -> (a -> ExitCase b -> WriterT w m c) -> (a -> WriterT w m b) -> WriterT w m (b, c) # | |
(MonadMask m, Monoid w) => MonadMask (WriterT w m) | |
Defined in Control.Monad.Catch mask :: ((forall a. WriterT w m a -> WriterT w m a) -> WriterT w m b) -> WriterT w m b # uninterruptibleMask :: ((forall a. WriterT w m a -> WriterT w m a) -> WriterT w m b) -> WriterT w m b # generalBracket :: WriterT w m a -> (a -> ExitCase b -> WriterT w m c) -> (a -> WriterT w m b) -> WriterT w m (b, c) # | |
MonadMask m => MonadMask (SeldaT b m) Source # | |
Defined in Database.Selda.Backend.Internal mask :: ((forall a. SeldaT b m a -> SeldaT b m a) -> SeldaT b m b0) -> SeldaT b m b0 # uninterruptibleMask :: ((forall a. SeldaT b m a -> SeldaT b m a) -> SeldaT b m b0) -> SeldaT b m b0 # generalBracket :: SeldaT b m a -> (a -> ExitCase b0 -> SeldaT b m c) -> (a -> SeldaT b m b0) -> SeldaT b m (b0, c) # | |
MonadMask m => MonadMask (ReaderT r m) | |
Defined in Control.Monad.Catch mask :: ((forall a. ReaderT r m a -> ReaderT r m a) -> ReaderT r m b) -> ReaderT r m b # uninterruptibleMask :: ((forall a. ReaderT r m a -> ReaderT r m a) -> ReaderT r m b) -> ReaderT r m b # generalBracket :: ReaderT r m a -> (a -> ExitCase b -> ReaderT r m c) -> (a -> ReaderT r m b) -> ReaderT r m (b, c) # | |
(MonadMask m, Monoid w) => MonadMask (RWST r w s m) | |
Defined in Control.Monad.Catch mask :: ((forall a. RWST r w s m a -> RWST r w s m a) -> RWST r w s m b) -> RWST r w s m b # uninterruptibleMask :: ((forall a. RWST r w s m a -> RWST r w s m a) -> RWST r w s m b) -> RWST r w s m b # generalBracket :: RWST r w s m a -> (a -> ExitCase b -> RWST r w s m c) -> (a -> RWST r w s m b) -> RWST r w s m (b, c) # | |
(MonadMask m, Monoid w) => MonadMask (RWST r w s m) | |
Defined in Control.Monad.Catch mask :: ((forall a. RWST r w s m a -> RWST r w s m a) -> RWST r w s m b) -> RWST r w s m b # uninterruptibleMask :: ((forall a. RWST r w s m a -> RWST r w s m a) -> RWST r w s m b) -> RWST r w s m b # generalBracket :: RWST r w s m a -> (a -> ExitCase b -> RWST r w s m c) -> (a -> RWST r w s m b) -> RWST r w s m (b, c) # |
A space efficient, packed, unboxed Unicode text type.
The Modified Julian Day is a standard count of days, with zero being the day 1858-11-17.
Instances
Enum Day | |
Eq Day | |
Data Day | |
Defined in Data.Time.Calendar.Days gfoldl :: (forall d b. Data d => c (d -> b) -> d -> c b) -> (forall g. g -> c g) -> Day -> c Day # gunfold :: (forall b r. Data b => c (b -> r) -> c r) -> (forall r. r -> c r) -> Constr -> c Day # dataTypeOf :: Day -> DataType # dataCast1 :: Typeable t => (forall d. Data d => c (t d)) -> Maybe (c Day) # dataCast2 :: Typeable t => (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c Day) # gmapT :: (forall b. Data b => b -> b) -> Day -> Day # gmapQl :: (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> Day -> r # gmapQr :: (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> Day -> r # gmapQ :: (forall d. Data d => d -> u) -> Day -> [u] # gmapQi :: Int -> (forall d. Data d => d -> u) -> Day -> u # gmapM :: Monad m => (forall d. Data d => d -> m d) -> Day -> m Day # gmapMp :: MonadPlus m => (forall d. Data d => d -> m d) -> Day -> m Day # gmapMo :: MonadPlus m => (forall d. Data d => d -> m d) -> Day -> m Day # | |
Ord Day | |
Ix Day | |
NFData Day | |
Defined in Data.Time.Calendar.Days | |
FormatTime Day | |
Defined in Data.Time.Format formatCharacter :: Char -> Maybe (TimeLocale -> Maybe NumericPadOption -> Maybe Int -> Day -> String) # | |
ParseTime Day | |
Defined in Data.Time.Format.Parse | |
SqlType Day Source # | |
SqlOrd Day Source # | |
Defined in Database.Selda |
Time of day as represented in hour, minute and second (with picoseconds), typically used to express local time of day.
Instances
This is the simplest representation of UTC. It consists of the day number, and a time offset from midnight. Note that if a day has a leap second added to it, it will have 86401 seconds.
Instances
Eq UTCTime | |
Data UTCTime | |
Defined in Data.Time.Clock.Internal.UTCTime gfoldl :: (forall d b. Data d => c (d -> b) -> d -> c b) -> (forall g. g -> c g) -> UTCTime -> c UTCTime # gunfold :: (forall b r. Data b => c (b -> r) -> c r) -> (forall r. r -> c r) -> Constr -> c UTCTime # toConstr :: UTCTime -> Constr # dataTypeOf :: UTCTime -> DataType # dataCast1 :: Typeable t => (forall d. Data d => c (t d)) -> Maybe (c UTCTime) # dataCast2 :: Typeable t => (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c UTCTime) # gmapT :: (forall b. Data b => b -> b) -> UTCTime -> UTCTime # gmapQl :: (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> UTCTime -> r # gmapQr :: (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> UTCTime -> r # gmapQ :: (forall d. Data d => d -> u) -> UTCTime -> [u] # gmapQi :: Int -> (forall d. Data d => d -> u) -> UTCTime -> u # gmapM :: Monad m => (forall d. Data d => d -> m d) -> UTCTime -> m UTCTime # gmapMp :: MonadPlus m => (forall d. Data d => d -> m d) -> UTCTime -> m UTCTime # gmapMo :: MonadPlus m => (forall d. Data d => d -> m d) -> UTCTime -> m UTCTime # | |
Ord UTCTime | |
Defined in Data.Time.Clock.Internal.UTCTime | |
NFData UTCTime | |
Defined in Data.Time.Clock.Internal.UTCTime | |
FormatTime UTCTime | |
Defined in Data.Time.Format formatCharacter :: Char -> Maybe (TimeLocale -> Maybe NumericPadOption -> Maybe Int -> UTCTime -> String) # | |
ParseTime UTCTime | |
Defined in Data.Time.Format.Parse | |
SqlType UTCTime Source # | |
SqlOrd UTCTime Source # | |
Defined in Database.Selda |
The UUID type. A Random
instance is provided which produces
version 4 UUIDs as specified in RFC 4122. The Storable
and
Binary
instances are compatible with RFC 4122, storing the fields
in network order as 16 bytes.
Instances
Eq UUID | |
Data UUID | |
Defined in Data.UUID.Types.Internal gfoldl :: (forall d b. Data d => c (d -> b) -> d -> c b) -> (forall g. g -> c g) -> UUID -> c UUID # gunfold :: (forall b r. Data b => c (b -> r) -> c r) -> (forall r. r -> c r) -> Constr -> c UUID # dataTypeOf :: UUID -> DataType # dataCast1 :: Typeable t => (forall d. Data d => c (t d)) -> Maybe (c UUID) # dataCast2 :: Typeable t => (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c UUID) # gmapT :: (forall b. Data b => b -> b) -> UUID -> UUID # gmapQl :: (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> UUID -> r # gmapQr :: (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> UUID -> r # gmapQ :: (forall d. Data d => d -> u) -> UUID -> [u] # gmapQi :: Int -> (forall d. Data d => d -> u) -> UUID -> u # gmapM :: Monad m => (forall d. Data d => d -> m d) -> UUID -> m UUID # gmapMp :: MonadPlus m => (forall d. Data d => d -> m d) -> UUID -> m UUID # gmapMo :: MonadPlus m => (forall d. Data d => d -> m d) -> UUID -> m UUID # | |
Ord UUID | |
Read UUID | |
Show UUID | |
Storable UUID | |
Defined in Data.UUID.Types.Internal | |
Binary UUID | |
NFData UUID | |
Defined in Data.UUID.Types.Internal | |
Hashable UUID | |
Defined in Data.UUID.Types.Internal | |
Random UUID | |
SqlType UUID Source # |
|