Hi Felipe,
I was further studying Esqueleto (after some successful previous experiences), and I thought the best way to start would be to analyze the tests. Great way to have examples, by the way!
Anyhow, I noticed all the tests were being run in SQLite, so I set out to try them in PostgreSQL, since that will be the database I'll be using. Simple enough, I added the dependency to the Cabal and changed the database initializing string:
withPostgresqlConn "host=localhost port=5432 user=xpto dbname=esqueleto" .
However, I was a bit surprised at first that some tests were not passing. Well, I then remember that you clearly stated that:
We do not try to hide the differences between DBMSs from you, and esqueleto code that works for one database may not work on another.
Nevertheless, not all failing tests are falling under this category, and in at least one case (the first) a test can be simply modified to also run on Postgres.
I was in doubt if I should open a issue for each one of them, but I opted to group it all on one issue. If you prefer, I can split it out.
So, one by one:
1) IN works for subList_select
This test assumes a given order, which is however not made explicit. By pure chance, I guess, PostgreSQL returns the two rows in the inverse order. By making the ordering explicit, this test now passes, without influencing SQLite results.
jcristovao@84f2f08
2) sum function does not necessarily return the same type it receives
While in SQLite and MySQL the sum function returns the same type it receives, this is not the case in Postgres
http://www.postgresql.org/docs/9.2/static/functions-aggregate.html
In fact, when summing to 'BigInts', the result is 'Numeric', which translates to Rational in the underlying Postrgres haskell libs.
To support this, a change is necessary in the code, specifying this:
sum_ :: (PersistField a, PersistField b) => expr (Value a) -> expr (Value (Maybe b))
jcristovao@161621c
However, while this change has no impact on the sum_ test under SQLite, since its expected result type is already properly annotated, when run under Postgres this type needs to be changed to Rational.
So, what would be your preferred approach?
- Focus the tests only on SQLite
- Create a separate test file (plus eventually an associated script) for each DB
While I agree that 1) is faster, it would certainly help Esqueleto adoption if a user is certain of which tests / features work on its DB of choice. I would, of course, be willing to volunteer the modifications made to run under PostgreSQL.
3) random_ return type
A similar problem. No type signature change is required in the src code, but while SQLite returns an Integer, Postgres returns a double.
4) ASC and DESC with null fields
This affects tests:
- select/orderBy works with two ASC field
- select/orderBy works with one ASC and one DESC field
- update works on a simple example
- lists of values EXISTS works for subList_select
The crux of the problem is that Postrgres considers NULLs bigger than everything else, while SQLite and MySQL consider the exact opposite. Postgres can be made to support a similar behaviour by specifying:
orderByType ASC = " ASC NULLS FIRST"
orderByType DESC = " DESC NULLS LAST"
But, as it would be expected, this syntax is not supported by the other DBs. So, either we add a dependency for CPP like #ifdefs, or actively maintain a different branch or file (if we want consistent behaviour for all backends). Otherwise, the tests can be modified / branched to fit PostgreSQL behaviour. I don't know... what's your take on this?
5) IN works for insertSelect FAILED
Well, this one I believe its a bug in the code, as I described here, but one that unfortunately I don't know enough to solve.
Sorry for the long post, will be glad to hear your input,
Abraço
EDIT: You can find here my fork with only test 5) failing.