What is Selda?
Selda is an EDSL — an embedded domain-specific language — for defining, querying and modifying relational databases from Haskell. The same type-safe Selda query can be executed unmodified on either PostgreSQL or SQLite, making Selda ideal for prototyping as well as for taking the step from prototype to real application.
Through its monadic interface, Selda supports writing queries in a linear, natural style. The generated SQL code is guaranteed to be correct, type-safe and executable on all supported backends. With a minimalist approach to dependencies, Selda is lightweight enough to be suitable for inclusion in libraries as well as full applications. All non-essential features are optional, either through configuration flags or through separate add-on packages.
Features
- Type-safe queries, inserts, updates and deletes
- Monadic query language with general inner queries
- Seamless prepared statements
- Typed migrations
- Upserts, transactions, indexes and constraints
- Minimal dependencies
- Backends for PostgreSQL and SQLite
- JSON processing on supported backends
- ...and much more!
Installation
$ cabal update
$ cabal install selda-sqlite selda-postgresql
$ cabal update
$ cabal install selda-sqlite
$ cabal install selda-postgresql
By example
{-# LANGUAGE DeriveGeneric, OverloadedStrings, OverloadedLabels #-}
import Database.Selda
import Database.Selda.SQLite
data Pet = Dog | Horse | Dragon
deriving (Show, Read, Bounded, Enum)
instance SqlType Pet
data Person = Person
{ name :: Text
, age :: Int
, pet :: Maybe Pet
} deriving Generic
instance SqlRow Person
people :: Table Person
people = table "people" [#name :- primary]
main = withSQLite "people.sqlite" $ do
createTable people
insert_ people
[ Person "Velvet" 19 (Just Dog)
, Person "Kobayashi" 23 (Just Dragon)
, Person "Miyu" 10 Nothing
]
adultsAndTheirPets <- query $ do
person <- select people
restrict (person ! #age .>= 18)
return (person ! #name :*: person ! #pet)
liftIO $ print adultsAndTheirPets