jgaskins / perpetuity

Persistence gem for Ruby objects using the Data Mapper pattern
http://jgaskins.org/blog/2012/04/20/data-mapper-vs-active-record/
MIT License
250 stars 14 forks source link

Intermediate query form #44

Open jgaskins opened 10 years ago

jgaskins commented 10 years ago

Looking at the query serialization for both the MongoDB and Postgres adapters, there is a lot of similarity (the QueryAttribute classes are nearly identical) and I think a lot of that could be extracted back into the core perpetuity gem and stored in some intermediate form that the database adapters would build their queries from.

The Perpetuity::Retrieval class already has something like this, and I think we should extract that and build on it to add support for things like inserts, updates and deletions. Along with #43, this would allow us to translate between the object-attribute name and the database-column name more easily.

jgaskins commented 10 years ago

If the queries went from this:

mapper.select { |foo| (foo.name == 'bar') & (foo.baz == 'quux') }

to this:

[[:name, :==, 'bar'], :and, [:base, :==, 'quux']]

That has everything we need for the most common cases (equality/inequality). But if we want to do anything more involved (and we do), this particular format won't work.

For queries like mapper.select { |article| article.author.id == '1234' } (both the Postgres and MongoDB adapters support this), we would need to allow representing an attribute's subattributes. Maybe [[{ author: :id }, :==, '1234']]? I'm not sure.

Similarly, we need a way to indicate that we want to pass a method call to the database adapter. Adding support for downcase to translate mapper.select { |user| user.email.downcase == 'me@example.com' } into the equivalent SQL: lower(email) = 'me@example.com'. Seeing as getting an attribute's attributes is also a DB-level thing, this might end up being the exact same thing.

I also want to keep in mind that, for the future where we're able to run JOIN queries, there needs to be a way to indicate which collection/table that attribute is in.