I am trying to understand the benefits of building SQL using the object-oriented DSL constructor and parameterizing a raw SQL string. After researching / implementing the same query in three ways, I notice that raw SQL is by far the easiest to read. This begs the question: "why jump through a hoop?" Why not just declare and use raw SQL?
Here is what I came up with:
First, I assume that this makes SQL more portable, since it can then be used by any database with an adapter. It's probably big, right? However, isn't most T-SQL easy to understand for most databases?
Secondly, it provides a query object that can be reused - as a basis for other queries, a chain with names, etc.
What is the main return on investment you realize by creating your own SQL instead of declarations?
def instances_of_sql(ttype_id) #raw sql ttype_id = get(ttype_id).try(:id) ti = get('tmdm:type-instance') inst = get('tmdm:instance') type = get('tmdm:type') self.class.send :sanitize_sql, [%{ SELECT t.* FROM associations a JOIN roles type ON type.association_id = a.id AND type.ttype_id = ? JOIN roles inst ON inst.association_id = a.id AND inst.ttype_id = ? JOIN topics t ON t.id = inst.topic_id WHERE a.topic_map_id IN (?) AND a.ttype_id = ? AND type.topic_id = ? }, type.id, inst.id, self.ids, ti.id, ttype_id] end def instances_of_sql(ttype_id) #sequel ttype_id = get(ttype_id).try(:id) ti = get('tmdm:type-instance') ir = get('tmdm:instance') tr = get('tmdm:type') DB.from(:associations.as(:a)). join(:roles.as(:tr), :tr__association_id => :a__id, :tr__ttype_id => tr[:id]). join(:roles.as(:ir), :ir__association_id => :a__id, :ir__ttype_id => ir[:id]). join(:topics.as(:t), :t__id => :ir__topic_id). where(:a__topic_map_id => self.ids). where(:a__ttype_id => ti[:id]). where(:tr__topic_id => ttype_id). select(:t.*).sql end def instances_of_sql(ttype_id) #arel ttype_id = get(ttype_id).try(:id) ti = get('tmdm:type-instance') inst = get('tmdm:instance') type = get('tmdm:type') #tables t = Topic.arel_table a = Association.arel_table tr = Role.arel_table ir = tr.alias a. join(tr).on(tr[:association_id].eq(a[:id]),tr[:ttype_id].eq(type[:id])). join(ir).on(ir[:association_id].eq(a[:id]),ir[:ttype_id].eq(inst[:id])). join(t).on(t[:id].eq(ir[:topic_id])). where(a[:topic_map_id].in(self.ids)). where(a[:ttype_id].eq(ti[:id])). where(tr[:topic_id].eq(ttype_id)). project('topics.*').to_sql end
I fully appreciate these areas and see how their chains can be useful. I am not worried about accessing the relevant records using the model. I'm just talking about creating a complex query.
ruby tsql arel sequel
Mario
source share