Tuesday, June 19, 2012

An ORM for Perl 6

I've been using sqlalchemy in Python quite a bit of late, but as I play around more and more with Perl 6 it seems to me that the sqlalchemy model of ORM for Perl 6 would be incorrect. Certainly, the basic concept that you tie objects to database tables and rows still makes sense, but the way you gain access to those objects is probably going to want to be very different in the two languages.

Here's a bit of sqlalchemy from an online tutorial:

mary = session.query(User).selectfirst(users.c.name=='Mary')

So, we have a session object. I think that makes sense for both languages. Then there's a query to which we pass our User table spec. Perfectly sane. Then there's this "selectfirst" thing, which is really shorthand for "select" with the given arguments and then the "first" method called on that result.

In this example, we're not actually comparing "users.c.name" to "Mary". Instead, users.c.name overrides comparison and returns an object that describes to selectfirst that it should perform an equality comparison in the where clause between the "name" column and the string "Mary".

This is about as close as Python can get to a mini-language because you can't override the parser. However, Perl 6 lets you do just that...

method mary($session) is parsed(::ORM::first) {
  select($session)
  from self
  where name == "Mary"  
}

But, isn't the point of an ORM to remove all of that ugly SQL?! Well, no. The point of an ORM is to give you native language controls over databases in a portable way. Our mini-language might look like SQL, but is actually just Perl with a different parsing filter, essentially the same as the filter provided to the "selectfirst" command in the Python example.

If you were to write this out in Perl 6, it might then turn into something like:

method mary($session) {
  select($session, :source(self),
    :filter(:lhs(self!coldef<name>), :rhs("Mary"), :op("==")).first);
}


But if we're talking to an SQL database, why not use something that looks more like SQL? I'm still noodling with this and thinking about what makes sense, but when I get to sitting down and thinking about an ORM for Perl 6 (if someone else hasn't already), then this will definitely be my starting point.