[database-devel] [ANNOUNCE] esqueleto, a type-safe EDSL for SQL queries

Felipe Almeida Lessa felipe.lessa at gmail.com
Wed Sep 12 14:47:18 CEST 2012


[cross-posting to web-devel]

On Wed, Sep 12, 2012 at 6:28 AM, Leon Smith <leon.p.smith at gmail.com> wrote:
> I am curious to know why persistent is a dependency,   given that it sounds
> like esqueleto focuses on generating raw SQL.
>
> Is it to get a more consistent interface across multiple database backends?
> To handle schemas or migrations?   Something else I'm missing entirely?

TL;DR: Mainly the schema.  Esqueleto could stop using persistent if we
wanted but I don't know how many people would like to see this working
and it is by no means trivial.



Its main use of persistent is actually on the frontend, on the EDSL
that you use.  Using persistent we get a type-safe representation of
the schema for free: entities and their fields.  So when you say

  where_ (p ^. BlogPostTitle ==. val title)

that BlogPostTitle is a constructor representing a field of entity
BlogPost, which was created by persistent.  The fact that p is a
BlogPost is type-checked.  The fact that title is, e.g., Text is
type-checked.

If I didn't use persistent, I'd have to ask the user to write this
boilerplate code himself.  If I didn't use persistent but the user
did, it would be probably just a matter of implementing a lot of type
class instances with trivial definitions.  If neither I not my user
used persistent, you'd probably have to implement a lot more
(especially for the next point).



It's also very convenient to use persistent on the backend.  It
already has everything you need to serialize and deserialize fields
and entities, and a few bits more (such as escaping).  This is also
about schema, and we could also drop persistent if we gave the user
the responsibility of writing a lot of boilerplate.



We decided to use persistent as esqueleto's backend also because
that's what we use on our company.  We don't know of any other
alternative that brings what persistent has for us: semi-intelligent
migrations, not so much boilerplate due to TH, good support to MySQL
via Bryan O'Sullivan's libraries (this bit is persistent-mysql and we
developed the library in-house), type-safety on everything it provides
(and now much more due to esqueleto), and non-slowness (I've never
seen a benchmark between database APIs, but we know that
persistent---and esqueleto---has been written with performance in
mind).  Even if there was an alternative, it would be very wasteful to
change all of our codebase *unless* it brought something nice to the
table that persistent does not have.



Having said all that, it *may* be possible to abstract persistent out
of esqueleto and avoid boilerplate for persistent's users by using the
ConstraintKinds extension.  All constraints that you see on the EDSL's
interface could come from type families inside Esqueleto's type class.
 In order for this abstraction to be useful, we'd also need to
abstract persistent away from the SQL backend, which may require a
type class with a lot more internal methods but which persistent users
will never need to see.

This may be a nice idea should there be anyone wanting to use
esqueleto without persistent.  But, like I said above, you'd still
need to define some boilerplate about your entities.  I see two kinds
of users that may like such approach:

  - Users that use completely raw interfaces (such as directly using
{mysql,postgresql}-simple libraries).  They will need to define a lot
boilerplate by themselves, including the SQL backend type class.  I'd
say that these users should instead define a persistent schema, which
will also need some boilerplate but a lot less, and you get persistent
for free in the process.

  - Users of HaskellDB that need to issue a couple of raw queries here
and there.  It would be technically very interesting to use both
approaches at the same time.  Given that HaskellDB already has
constructors for entities and fields, it would be just a matter of
somehow teaching esqueleto how to use it (which may be easy but I
never thought about it).  However, I wonder how many exist on this
category.



So, while possible to stop using persistent, I'll probably not do
anything in this direction unless I see that there is some interest in
doing so (and not only for the sake of abstracting things).  However,
I'd accept a pull request for this in a heartbeat *if* it didn't add
any boilerplate for persistent users.  I could also accept something
that incurs boilerplate overhead for persistent users, but it would
not be in a heartbeat =).


Cheers!

-- 
Felipe.



More information about the database-devel mailing list