packages feed

ribbit 0.3.0.1 → 0.4.0.0

raw patch · 3 files changed

+121/−38 lines, 3 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

- Database.Ribbit: data X l r
- Database.Ribbit: instance forall k1 k2 (l :: k2) (r :: k1) (lname :: GHC.Types.Symbol) (rname :: GHC.Types.Symbol). (Database.Ribbit.Table l, Database.Ribbit.Table r, GHC.TypeLits.KnownSymbol lname, GHC.TypeLits.KnownSymbol rname) => Database.Ribbit.Table (Database.Ribbit.X (Database.Ribbit.As l lname) (Database.Ribbit.As r rname))
+ Database.Ribbit: data DeleteFrom table
+ Database.Ribbit: instance forall k (table :: k) (name :: GHC.Types.Symbol) (moreTables :: [*]). (Database.Ribbit.Table table, GHC.TypeLits.KnownSymbol name) => Database.Ribbit.Table (Database.Ribbit.As table name : moreTables)
+ Database.Ribbit: instance forall k (table :: k). GHC.TypeLits.KnownSymbol (Database.Ribbit.Name table) => Database.Ribbit.Render (Database.Ribbit.DeleteFrom table)

Files

README.md view
@@ -8,8 +8,8 @@             - [Conditionals](#conditionals)             - [Limited `CREATE TABLE` support.](#limited-create-table-support)             - [`INSERT INTO` support.](#insert-into-support)+            - [`DELETE FROM` support.](#delete-from-support)     - [Roadmap](#roadmap)-        - [DELETE support](#delete-support)         - [UPDATE support](#update-support)         - [Flesh out Haskell to PostgreSQL type mapping.](#flesh-out-haskell-to-postgresql-type-mapping)     - [How it compares with other libraries.](#how-it-compares-with-other-libraries)@@ -69,7 +69,7 @@ We support queries of the form:  ```haskell-type MyQuery = Select '["t1.field1", "t2.field2"] `From` MyTable1 `As` "t1" `X` MyTable2 `As` "t2"+type MyQuery = Select '["t1.field1", "t2.field2"] `From` '[MyTable1 `As` "t1", MyTable2 `As` "t2"] ```  #### Conditionals@@ -129,14 +129,29 @@   (Only 1 :> Only "Bob Marley" :> Only 36) ``` -## Roadmap+#### `DELETE FROM` support. -This is what I plan to work on next:+Basic deletes are supported: -### DELETE support+```haskell+type MyDeleteEveryone = DeleteFrom PeopleTable+type MyDeleteById = DeleteFrom PeopleTable `Where` id `Equals` (?) -Support delete operations.+execute+  conn+  (Proxy :: Proxy MyDeleteEveryone)+  () +execute+  conn+  (Proxy :: Proxy MyDeleteById)+  (Only 1)+```++## Roadmap++This is what I plan to work on next:+ ### UPDATE support  Support update operations.@@ -181,11 +196,11 @@    Then you would be free to deconstruct this type (using type families),   transform it into another schema, generate customized `CREATE TABLE`-  statements if the (forthcoming) ones provided aren't good enough for your-  back-end or use case... that sort of thing. As a somewhat contrived example:-  maybe, for who knows what reason, you never want to allow null values in your-  database. You can write a type family that can inspect every field in an-  arbitrary schema, replacing all the `Maybe a` with just `a`, like:+  statements if the ones provided aren't good enough for your back-end or+  use case... that sort of thing. As a somewhat contrived example: maybe,+  for who knows what reason, you never want to allow null values in your+  database. You can write a type family that can inspect every field in+  an arbitrary schema, replacing all the `Maybe a` with just `a`, like:    ```haskell   -- With -XPolyKinds
ribbit.cabal view
@@ -1,6 +1,6 @@  name:                ribbit-version:             0.3.0.1+version:             0.4.0.0 synopsis:            Type-level Relational DB combinators. description:         Ribbit is yet another type safe relational database                      library for Haskell, heavily inspired by the
src/Database/Ribbit.hs view
@@ -47,6 +47,9 @@   -- ** Inserting values   -- $insert +  -- ** Deleting values+  -- $delete+   -- * Schema Definition Types   (:>)(..),   Table(..),@@ -55,12 +58,14 @@   -- * Query Combinators   Select,   From,-  X,   As,   Where,    -- * Insert Combinators   InsertInto,+  +  -- * Delete Combinators+  DeleteFrom,    -- ** Condition Conbinators   And,@@ -160,7 +165,10 @@ -- > type MyQuery = -- >   Select '["e.name", "e.salary"] -- >   `From`--- >     Company `As` "c" `X` Employee `As` "e"+-- >       '[+-- >         Company `As` "c",+-- >         Employee `As` "e"+-- >       ] -- >   `Where` -- >     "c.id" `Equals` "e.company_id" -- >     `And` "c.name" `Equals` (?)@@ -259,7 +267,35 @@ -- >     (Proxy :: Proxy InsertEmployee) -- >     (Only 1 :> Only 1 :> Only "Rick" :> Only myBirthday) +-- $delete+-- Deleting a value is similar to inserting a value, but simpler because+-- you only have to specify the delete conditions (if there are any).+-- +-- e.g.:+--  +-- > type DeleteAllEmployees = DeleteFrom Employee+-- > type DeleteEmployeeById =+-- >   DeleteFrom Employee+-- >   `Where` "id" `Equals` (?)+-- +-- Then just execute the query, providing the appropriate query params.+-- +-- > do+-- >   let+-- >     employeeId :: Int+-- >     employeeId = ...+-- >   execute+-- >     conn+-- >     (Proxy :: Proxy DeleteEmployeeById)+-- >     (Only employeeId)+-- >+-- >   -- Or maybe delete all employees.+-- >   execute+-- >     conn+-- >     (Proxy :: Proxy DeleteAllEmployees)+-- >     () + {- | "SELECT" combinator, used for starting a @SELECT@ statement. -} data Select fields @@ -317,11 +353,6 @@ infixr 7 `Or`  -{- | Cross product operator for FROM clauses. -}-data X l r-infixr 7 `X`-- {- | "AS" combinator, used for attaching a name to a table in a FROM clause. -} data As relation name infix 8 `As`@@ -399,7 +430,6 @@   LookupType name a context = NotInSchema name context  - {- |   Type class for defining your own tables. The primary way for you to   introduce a new schema is to instantiate this type class for one of@@ -421,20 +451,42 @@   type DBSchema relation  {- | Cross product -}-instance (Table l, Table r, KnownSymbol lname, KnownSymbol rname) => Table (l `As` lname `X` r `As` rname) where-  type DBSchema (l `As` lname `X` r `As` rname) =+instance+    (Table table, KnownSymbol name)+  =>+    Table ((table `As` name) : moreTables)+  where+    type DBSchema ((table `As` name) : moreTables) =+      CrossProductSchema ((table `As` name) : moreTables)+    type Name ((table `As` name) : moreTables) =+      CrossProductName ((table `As` name) : moreTables)+++{- | Produce the schema of a cross product. -}+type family CrossProductSchema cp where+  CrossProductSchema '[table `as` name] =     Flatten (-      AliasAs lname (DBSchema l)-      :> AliasAs rname (DBSchema r)+      AliasAs name (DBSchema table)     )-  type Name (l `As` lname `X` r `As` rname) =-    Name l+  CrossProductSchema ((table `As` name) : moreTables) =+    Flatten (+      AliasAs name (DBSchema table)+      :> CrossProductSchema moreTables+    )+++{- | Product the renderable "name" of a cross product. -}+type family CrossProductName cp where+  CrossProductName '[table `As` name] = +    Name table     `AppendSymbol` " as "-    `AppendSymbol` lname-    `AppendSymbol` ", "-    `AppendSymbol` Name r+    `AppendSymbol` name+  CrossProductName ((table `As` name) : moreTables) = +    Name table     `AppendSymbol` " as "-    `AppendSymbol` rname+    `AppendSymbol` name+    `AppendSymbol` ", "+    `AppendSymbol` CrossProductName moreTables   {- |@@ -469,6 +521,8 @@ type family ArgsType query where   ArgsType (_ `From` relation `Where` conditions) =     ArgsType (DBSchema relation, conditions)+  ArgsType (DeleteFrom relation `Where` conditions) =+    ArgsType (DBSchema relation, conditions)   ArgsType (InsertInto relation '[]) =     TypeError ('Lit.Text "Insert statement must specify at least one column.")   ArgsType (InsertInto relation fields) =@@ -654,15 +708,25 @@   render _proxy = "?"  {- INSERT -}-instance (ReflectFields fields, KnownSymbol (Name table)) => Render (InsertInto table fields) where+instance+    (ReflectFields fields, KnownSymbol (Name table))+  =>+    Render (InsertInto table fields)+  where+    render _proxy =+      let+        fields :: [Text]+        fields = reflectFields (Proxy @fields)+      in+        "insert into " <> symbolVal (Proxy @(Name table))+        <> " (" <> T.intercalate ", " fields <> ")"+        <> " values (" <> T.intercalate ", " (const "?" <$> fields) <> ");"+++{- DELETE -}+instance (KnownSymbol (Name table)) => Render (DeleteFrom table) where   render _proxy =-    let-      fields :: [Text]-      fields = reflectFields (Proxy @fields)-    in-      "insert into " <> symbolVal (Proxy @(Name table))-      <> " (" <> T.intercalate ", " fields <> ")"-      <> " values (" <> T.intercalate ", " (const "?" <$> fields) <> ");"+    "delete from " <> symbolVal (Proxy @(Name table))   {- | Insert statement. -}@@ -676,5 +740,9 @@   reflectFields _proxy = [] instance (KnownSymbol a, ReflectFields more) => ReflectFields (a:more) where   reflectFields _proxy = symbolVal (Proxy @a) : reflectFields (Proxy @more)+++{- | Delete statement. -}+data DeleteFrom table