[ANN] relational-record - relational-algebraic query building DSL

Hello everybody, I am happy to announce relational-record library and its project page. relational-record is domain specific language for type-safe SQL query building, and database access API with compile time schema generators. Code is avaiable on github and hackage. https://github.com/khibino/haskell-relational-record/ http://hackage.haskell.org/package/relational-record/ Tutorial, examples and documentations are available from project page links. http://khibino.github.io/haskell-relational-record/ Supported features are below, * Type safe query building. * Composable query. * Outer join. * Aggregation. * Compile time compile code generation along with RDBMS schema. * Schema support of ProsgreSQL, SQLite3, MySQL, IBM DB2, MicroSoft SQL Server, and Oracle. Any comments, any questions about this library are welcome. -- Kei Hibino ex8k.hibino at gmail.com https://github.com/khibino/

On Sun, Dec 14, 2014 at 12:04 PM, Kei Hibino
I am happy to announce relational-record library and its project page.
relational-record is domain specific language for type-safe SQL query building, and database access API with compile time schema generators.
Congratulations on the release! It’s great to see more and more
interesting abstractions for relational databases in the Haskell
ecosystem.
It looks like this project shares many goals with Tom Ellis’ excellent
and recently released[1] Opaleye library. How would you say your
approach compares with Opaleye’s?
[1]:

On 14 December 2014 at 18:52, Manuel Gómez
Congratulations on the release! It’s great to see more and more interesting abstractions for relational databases in the Haskell ecosystem.
Hi * I chime in for the first time. Haskell is my favourite language. I really don't program in it, I have done it very little. I like more reading about Haskell (et al). What I really do, is work with geo(yay) data(yay)BaseManagementSystems(meh) and SQL(yuck). Yes, despite SQLs yuckiness I feel myself most naturally among NATURAL JOIN and other relationally algebraic friends. I'm very sorry, but I had a strong gut reaction to Manuels sentiment. Really?! What's so great about it? Isn't this rather a sign that something is askew? For such an important, ubiquitous yet mundane task as accessing database there shouldn't be so many ad hoc half-baked (sorry - with some limitations) solutions. That's unfair, I know. I look at those examples and think, this is not the Haskell I'd like to write and despite type safety and composability, which are great features, it's not even the query language I'd like to write. Ie it's not better than SQL, yet. I mean, I understand the need to talk to SQL DMBS-s. I guess I'm just sad and angry that the great talent of library authors is wasted on such endeavor. Of course no Haskell programmer wants to write SQL, because the L is so askew in SQL. (apologies to Hugh Darwen). BUT, but. If Haskell hasn't got tuples as in relations (named, not ordered), type system such that tuple types' arity is not fixed (if that's the correct way to put it) and types for sets of such tuples aka relation type, then how can Haskell support databases and relational algebra NATURALLY? On the other hand, if Haskell had those, it would be quite a relational language, right? And a GREAT one, no? Anyway, bye! Riivo

On Wed, Dec 17, 2014 at 07:04:12PM +0200, Riivo Kolka wrote:
On 14 December 2014 at 18:52, Manuel Gómez
wrote: Congratulations on the release! It’s great to see more and more interesting abstractions for relational databases in the Haskell ecosystem. [...] I'm very sorry, but I had a strong gut reaction to Manuels sentiment. Really?! What's so great about it? Isn't this rather a sign that something is askew? For such an important, ubiquitous yet mundane task as accessing database there shouldn't be so many ad hoc half-baked (sorry - with some limitations) solutions. That's unfair, I know.
Hello Riivo, It's not clear to me from your message whether you've looked at Opaleye, a relation query embedded domain specific language for Haskell http://hackage.haskell.org/package/opaleye I wrote it, so all due caveats about my opinion apply, but I do not consider Opaleye either ad hoc or half-baked. Opaleye has a solid theoretical foundation and thorough attention has been given to its semantics.
I look at those examples and think, this is not the Haskell I'd like to write and despite type safety and composability, which are great features, it's not even the query language I'd like to write. Ie it's not better than SQL, yet.
If you feel this way about writing code using Opaleye perhaps you could be more specific so I can get a clearer understanding of the issues involved. [...]
If Haskell hasn't got tuples as in relations (named, not ordered), type system such that tuple types' arity is not fixed (if that's the correct way to put it) and types for sets of such tuples aka relation type, then how can Haskell support databases and relational algebra NATURALLY? On the other hand, if Haskell had those, it would be quite a relational language, right? And a GREAT one, no?
I should mention at this point that I do not consider "relational algebra" to be a paragon to which to aspire. There is a lot of value in that body of work, but in the light of developments in programming language semantics over the last forty years relational algebra really appears to need an overhaul. (Technical note: One thing I noticed when writing Opaleye is that restriction, projection and inner join are different sorts of operation than aggregation and outer join, the former being what are called "algebraic operations", the latter not. I think the only way this observation can be made is if you encode relational algebra in a typed setting.) Opaleye is an implementation of relational algebra to about the same extent that Haskell is an implementation of the untyped lambda calculus, and I'm very happy with that difference between them. Tom

17.12.2014 19:37 kirjutas kuupäeval "Tom Ellis" < tom-lists-haskell-cafe-2013@jaguarpaw.co.uk>:
On Wed, Dec 17, 2014 at 07:04:12PM +0200, Riivo Kolka wrote:
On 14 December 2014 at 18:52, Manuel Gómez
wrote: Congratulations on the release! It’s great to see more and more interesting abstractions for relational databases in the Haskell ecosystem. [...] I'm very sorry, but I had a strong gut reaction to Manuels sentiment. Really?! What's so great about it? Isn't this rather a sign that something is askew? For such an important, ubiquitous yet mundane task as accessing database there shouldn't be so many ad hoc half-baked (sorry - with some limitations) solutions. That's unfair, I know.
Hello Riivo,
It's not clear to me from your message whether you've looked at Opaleye, a relation query embedded domain specific language for Haskell
http://hackage.haskell.org/package/opaleye
I wrote it, so all due caveats about my opinion apply, but I do not
consider
Opaleye either ad hoc or half-baked. Opaleye has a solid theoretical foundation and thorough attention has been given to its semantics.
Tom I feel now really bad I wrote it that way. I'm actually excited about Haskell<>relational. How it can work. I may be going back to reading and thinking instead of posting inflammatory messages. I'm not comfortable going technical. I'm afraid It may take longer than you would expect for me to understand theoretical foundation of opaleye. Though I think I understand the foundation of relational theory. Riivo

On Wed, Dec 17, 2014 at 10:12:36PM +0200, Riivo Kolka wrote:
I'm afraid It may take longer than you would expect for me to understand theoretical foundation of opaleye. Though I think I understand the foundation of relational theory.
My aim with Opaleye is very much that no one needs to know any theory in order to use it!

Hi Manuel, I'm answering to you as a contributor of HRR.
It looks like this project shares many goals with Tom Ellis’ excellent and recently released[1] Opaleye library. How would you say your approach compares with Opaleye’s?
We got to know Opaleye just before we released HRR. We have not compared HRR with Opaleye yet. They are really independent. To be fair, would you enumerate technical questions? We would love to answer. And it would be nice if Tom will answer to them, too. P.S. HRR has been already used in the backend systems to express complex SQLs in Asahi-Net (an ISP in Japan) more than one year. It's not a toy package. Regards, --Kazu

From: Manuel Gómez
On Sun, Dec 14, 2014 at 12:04 PM, Kei Hibino
wrote: I am happy to announce relational-record library and its project page.
relational-record is domain specific language for type-safe SQL query building, and database access API with compile time schema generators.
Congratulations on the release! It’s great to see more and more interesting abstractions for relational databases in the Haskell ecosystem.
It looks like this project shares many goals with Tom Ellis’ excellent and recently released[1] Opaleye library. How would you say your approach compares with Opaleye’s?
[1]:
Relational Record and Opaleye resembles in approach of building not aggregated SQL query. Opaleye's method using arrow notation is very cool. So I try thin wrapper using Kleisli arrow. https://gist.github.com/khibino/57405584b168d98fd1e8 If not arrow version is like below,
personAndJoin :: QuerySimple (Projection Flat (Person, Birthday)) personAndJoin = do p <- query person b <- query birthday wheres $ p ! Person.name' .=. b ! Birthday.name' return $ p >< b
Arrow version is like this with this wrapper.
personAndJoinA :: QuerySimple () (Projection Flat (Person, Birthday)) personAndJoinA = proc () -> do p <- query -< person b <- query -< birthday wheres -< p ! Person.name' .=. b ! Birthday.name' returnA -< p >< b
Aggregation approaches differ. Relational Record accumulates aggregated context into monad stack, and Opaleye does not. Relational Record basically accumulates various query state into monad stack like join product, group keys and ordering.

On Fri, Dec 19, 2014 at 12:39:01PM +0900, Kei Hibino wrote:
From: Manuel Gómez
Subject: Re: [Haskell-cafe] [ANN] relational-record - relational-algebraic query building DSL Date: Sun, 14 Dec 2014 12:22:25 -0430 On Sun, Dec 14, 2014 at 12:04 PM, Kei Hibino
wrote: I am happy to announce relational-record library and its project page.
relational-record is domain specific language for type-safe SQL query building, and database access API with compile time schema generators.
Congratulations on the release! It’s great to see more and more interesting abstractions for relational databases in the Haskell ecosystem.
It looks like this project shares many goals with Tom Ellis’ excellent and recently released[1] Opaleye library. How would you say your approach compares with Opaleye’s?
[1]:
Relational Record and Opaleye resembles in approach of building not aggregated SQL query.
Opaleye's method using arrow notation is very cool.
Opaleye uses arrows only because it is hard to implement a sensible semantics otherwise. See, for example, this bug report on HaskellDB which used a monad rather than an arrow https://github.com/m4dc4p/haskelldb/issues/22 Tom

On Fri, Dec 19, 2014 at 4:44 AM, Tom Ellis
Opaleye uses arrows only because it is hard to implement a sensible semantics otherwise. See, for example, this bug report on HaskellDB which used a monad rather than an arrow
I'm curious how arrows make it easier to deal with aggregation? Sounds pretty interesting ... Justin

On Fri, Dec 19, 2014 at 08:07:39AM -0800, Justin Bailey wrote:
On Fri, Dec 19, 2014 at 4:44 AM, Tom Ellis
wrote: Opaleye uses arrows only because it is hard to implement a sensible semantics otherwise. See, for example, this bug report on HaskellDB which used a monad rather than an arrow
I'm curious how arrows make it easier to deal with aggregation? Sounds pretty interesting ...
They don't make it "easier" to deal with aggregation, they just avoid some cases you don't want to have to implement. HaskellDB allows you to write a function like groupByAndSum :: (Expr String, Expr Int) -> Query (Expr String, Expr Int) and it is hard or impossible to give this sensible semantics in SQL. (The function you get doesn't have exactly this type because of HaskellDB's home-rolled record types, but it is effectively this). Arrows help avoid this. (Interestingly Postgres's recent LATERAL JOIN FEATURE may make the above possible.) Tom

On Fri, Dec 19, 2014 at 12:39:01PM +0900, Kei Hibino wrote:
From: Manuel Gómez
Subject: Re: [Haskell-cafe] [ANN] relational-record - relational-algebraic query building DSL Date: Sun, 14 Dec 2014 12:22:25 -0430 On Sun, Dec 14, 2014 at 12:04 PM, Kei Hibino
wrote: I am happy to announce relational-record library and its project page.
relational-record is domain specific language for type-safe SQL query building, and database access API with compile time schema generators.
Congratulations on the release! It’s great to see more and more interesting abstractions for relational databases in the Haskell ecosystem.
It looks like this project shares many goals with Tom Ellis’ excellent and recently released[1] Opaleye library. How would you say your approach compares with Opaleye’s?
[1]:
Relational Record and Opaleye resembles in approach of building not aggregated SQL query.
Opaleye's method using arrow notation is very cool.
Opaleye uses arrows only because it is hard to implement a sensible semantics otherwise. See, for example, this bug report on HaskellDB which used a monad rather than an arrow
https://github.com/m4dc4p/haskelldb/issues/22
Tom
In my -- Relational Record -- implementation, this issue does not exist like exmaple code below. Both not-finalized monad case (continuing table form building, justAgeOfFamilies0) and finzlined monad (reuse defined table form, justAgeOfFamilies1) are no problem. Key idea is separating out group-by accumulating state and aggregated key result. Operator 'groupBy' accumulates aggregate key into monad stack, and returns aggregated context-typed projection. In aggregated relation, query result type and order-by specified key type are checked to allow only aggregated context-typed projection.
{-# LANGUAGE TemplateHaskell, MultiParamTypeClasses, FlexibleInstances #-}
import Data.Int
import Database.Relational.Query import Database.Relational.Query.TH
$(defineTableDefault defaultConfig "PUBLIC" "my_table" [ ("person", [t| String |]) , ("family", [t| String |]) , ("age" , [t| Int32 |]) ] [] [0] (Just 0))
agesOfFamiliesQ :: QueryAggregate (Projection Aggregated (String, Maybe Int32)) agesOfFamiliesQ = do my <- query myTable gFam <- groupBy $ my ! family' return $ gFam >< sum' (my ! age')
justAgeOfFamilies0 :: Relation () (Maybe Int32) justAgeOfFamilies0 = aggregateRelation $ do pair <- agesOfFamiliesQ return $ pair ! snd'
-- *Main> justAgeOfFamilies0 -- SELECT ALL SUM (T0.age) AS f0 FROM PUBLIC.my_table T0 GROUP BY T0.family
agesOfFamilies :: Relation () (String, Maybe Int32) agesOfFamilies = aggregateRelation agesOfFamiliesQ
justAgeOfFamilies1 :: Relation () (Maybe Int32) justAgeOfFamilies1 = relation $ do pair <- query agesOfFamilies return $ pair ! snd'
-- *Main> justAgeOfFamilies1 -- SELECT ALL T1.f1 AS f0 -- FROM (SELECT ALL T0.family AS f0, SUM (T0.age) AS f1 -- FROM PUBLIC.my_table T0 GROUP BY T0.family) T1
main :: IO () main = do putStrLn "0" print justAgeOfFamilies0 putStrLn "1" print justAgeOfFamilies1
-- Kei Hibino ex8k.hibino at gmail.com

On Sat, Dec 20, 2014 at 01:50:16AM +0900, Kei Hibino wrote:
On Fri, Dec 19, 2014 at 12:39:01PM +0900, Kei Hibino wrote:
From: Manuel Gómez
Subject: Re: [Haskell-cafe] [ANN] relational-record - relational-algebraic query building DSL Date: Sun, 14 Dec 2014 12:22:25 -0430 On Sun, Dec 14, 2014 at 12:04 PM, Kei Hibino
wrote: I am happy to announce relational-record library and its project page.
relational-record is domain specific language for type-safe SQL query building, and database access API with compile time schema generators.
Congratulations on the release! It’s great to see more and more interesting abstractions for relational databases in the Haskell ecosystem.
It looks like this project shares many goals with Tom Ellis’ excellent and recently released[1] Opaleye library. How would you say your approach compares with Opaleye’s?
[1]:
Relational Record and Opaleye resembles in approach of building not aggregated SQL query.
Opaleye's method using arrow notation is very cool.
Opaleye uses arrows only because it is hard to implement a sensible semantics otherwise. See, for example, this bug report on HaskellDB which used a monad rather than an arrow
In my -- Relational Record -- implementation, this issue does not exist like exmaple code below.
Unfortunately I just discovered that Haskell Relational Record suffers from a worse issue: not just strange semantics, but a (SQL) crash bug: https://github.com/khibino/haskell-relational-record/issues/19 Designing a typesafe relational query language is *hard*. Opaleye is still the only SQL EDSL I am aware of that has natural semantics and whose design is typesafe. Sadly, at least for now, Haskell Relational Record doesn't meet the second condition. Tom
participants (6)
-
Justin Bailey
-
Kazu Yamamoto
-
Kei Hibino
-
Manuel Gómez
-
Riivo Kolka
-
Tom Ellis