On Sun, Sep 2, 2012 at 8:24 PM, Arthur Clemens <
arthur...@gmail.com> wrote:
> Do you have any tips to make this more efficient?
This is persistent's greatest weakness: it's difficult to do joins.
There's a completely generic way of doing joins on
Database.Persist.Query.Join [1]. However, the runJoin from this
module will run 2 SELECTs -- way better than your example but still
suboptimal. (And it also has the same drawbacks as the following
alternative.)
There's a SQL-specific way of doing joins on
Database.Persist.Query.Join.Sql. This runJoin will actually do a
JOIN. However there are many drawbacks. First of all, it's a PITA to
use. For your example, you'd need to do something like (completely
untested -- actually, I don't know if runJoin applies to your example)
runDB $ runJoin $ SelectOneMany [] [] [] [Asc ProductName]
(ProductCategory <-.) productCategory False
and even then you'll have to massage the resulting data type. The
second biggest drawback is that it works only for simple joins on two
tables. For example, it won't work at all for a many-to-many
relationship.
So, these are the only two ways of safely doing JOINs on persistent
without resorting to doing the JOIN by yourself (like you did).
There's a third, unsafe way: using rawSql [3]. Like the name implies,
you are able to directly write SQL. This comes with all the caveats
of writing raw SQL queries that we're used to seeing. Also, it
wouldn't work for your particular example: you're running an OUTER
JOIN and currently rawSql does not have support for Maybes [4].
And then there's the fourth, hardest and unsafest way: using withStmt
[5]. It's actually not hard to use, but completely manual. There are
so many ways of shooting yourself in the foot that I won't even go
into details.
So that's it: there's no good, recommend way of doing JOINs with
persistent right now. However, we're not giving up yet! There *are*
ways of getting the job done and we do get the job done, but we're
searching for nice solutions! For example, there has been some
renewed interest on HaskellDB and how to use it with persistent. So
keep tuned and don't be afraid to hack =D.
Cheers, =)
[1]
http://hackage.haskell.org/packages/archive/persistent/1.0.0/doc/html/Database-Persist-Query-Join.html
[2]
http://hackage.haskell.org/packages/archive/persistent/1.0.0/doc/html/Database-Persist-Query-Join-Sql.html
[3]
http://hackage.haskell.org/packages/archive/persistent/1.0.0/doc/html/Database-Persist-GenericSql.html#v:rawSql
[4] However, I may fix this bug soon since I may need this feature myself.
[5]
http://hackage.haskell.org/packages/archive/persistent/1.0.0/doc/html/Database-Persist-GenericSql-Raw.html#v:withStmt
--
Felipe.