Module ScopedSearch::QueryBuilder::Field
In: lib/scoped_search/query_builder.rb

This module gets included into the Field class to add SQL generation.

Methods

Public Instance methods

This method construct join statement for a key value table It assume the following table structure

 +----------+  +---------+ +--------+
 | main     |  | value   | | key    |
 | main_pk  |  | main_fk | |        |
 |          |  | key_fk  | | key_pk |
 +----------+  +---------+ +--------+

uniq name for the joins are needed in case that there is more than one condition on different keys in the same query.

[Source]

     # File lib/scoped_search/query_builder.rb, line 271
271:       def construct_join_sql(key_relation, num )
272:         join_sql = ""
273:         connection = klass.connection
274:         key = key_relation.to_s.singularize.to_sym
275:         main = definition.klass.to_s.gsub(/.*::/,'').underscore.to_sym
276: 
277:         key_table = klass.reflections[key].table_name
278:         key_table_pk = klass.reflections[key].klass.primary_key
279: 
280:         value_table = klass.table_name.to_s
281:         value_table_fk_key = klass.reflections[key].association_foreign_key
282: 
283:         if klass.reflections[main]
284:           main_table = definition.klass.table_name
285:           main_table_pk = klass.reflections[main].klass.primary_key
286:           value_table_fk_main = klass.reflections[main].association_foreign_key
287: 
288:           join_sql = "\n  INNER JOIN #{connection.quote_table_name(value_table)} #{value_table}_#{num} ON (#{main_table}.#{main_table_pk} = #{value_table}_#{num}.#{value_table_fk_main})"
289:           value_table = " #{value_table}_#{num}"
290:         end
291:         join_sql += "\n INNER JOIN #{connection.quote_table_name(key_table)} #{key_table}_#{num} ON (#{key_table}_#{num}.#{key_table_pk} = #{value_table}.#{value_table_fk_key}) "
292: 
293:         return join_sql
294:       end

This method construct join statement for a key value table It assume the following table structure

 +----------+  +---------+
 | main     |  | key     |
 | main_pk  |  | value   |
 |          |  | main_fk |
 +----------+  +---------+

uniq name for the joins are needed in case that there is more than one condition on different keys in the same query.

[Source]

     # File lib/scoped_search/query_builder.rb, line 305
305:       def construct_simple_join_sql( num )
306:         connection = klass.connection
307:         main = definition.klass.to_s.gsub(/.*::/,'').underscore.to_sym
308:         key_value_table = klass.table_name
309: 
310:         main_table = definition.klass.table_name
311:         main_table_pk = klass.reflections[main].klass.primary_key
312:         value_table_fk_main = klass.reflections[main].options[:foreign_key]
313:         value_table_fk_main ||= klass.reflections[main].association_foreign_key
314: 
315:         join_sql = "\n  INNER JOIN #{connection.quote_table_name(key_value_table)} #{key_value_table}_#{num} ON (#{connection.quote_table_name(main_table)}.#{main_table_pk} = #{key_value_table}_#{num}.#{value_table_fk_main})"
316:         return join_sql
317:       end

[Source]

     # File lib/scoped_search/query_builder.rb, line 319
319:       def to_ext_method_sql(key, operator, value, &block)
320:         raise ScopedSearch::QueryNotSupported, "'#{definition.klass}' doesn't respond to '#{ext_method}'" unless definition.klass.respond_to?(ext_method)
321:         conditions = definition.klass.send(ext_method.to_sym,key, operator, value) rescue {}
322:         raise ScopedSearch::QueryNotSupported, "external method '#{ext_method}' should return hash" unless conditions.kind_of?(Hash)
323:         sql = ''
324:         conditions.map do |notification, content|
325:           case notification
326:             when :include then yield(:include, content)
327:             when :joins then yield(:joins, content)
328:             when :conditions then sql = content
329:             when :parameter then content.map{|c| yield(:parameter, c)}
330:           end
331:         end
332:         return sql
333:       end

Return an SQL representation for this field. Also make sure that the relation which includes the search field is included in the SQL query.

This function may yield an :include that should be used in the ActiveRecord::Base#find call, to make sure that the field is available for the SQL query.

[Source]

     # File lib/scoped_search/query_builder.rb, line 241
241:       def to_sql(operator = nil, &block) # :yields: finder_option_type, value
242:         num = rand(1000000)
243:         connection = klass.connection
244:         if key_relation
245:           yield(:joins, construct_join_sql(key_relation, num) )
246:           yield(:keycondition, "#{key_klass.table_name}_#{num}.#{connection.quote_column_name(key_field.to_s)} = ?")
247:           klass_table_name = relation ? "#{klass.table_name}_#{num}" : connection.quote_table_name(klass.table_name)
248:           return "#{klass_table_name}.#{connection.quote_column_name(field.to_s)}"
249:         elsif key_field
250:           yield(:joins, construct_simple_join_sql(num))
251:           yield(:keycondition, "#{key_klass.table_name}_#{num}.#{connection.quote_column_name(key_field.to_s)} = ?")
252:           klass_table_name = relation ? "#{klass.table_name}_#{num}" : connection.quote_table_name(klass.table_name)
253:           return "#{klass_table_name}.#{connection.quote_column_name(field.to_s)}"
254:         elsif relation
255:           yield(:include, relation)
256:         end
257:         column_name = connection.quote_table_name(klass.table_name.to_s) + "." + connection.quote_column_name(field.to_s)
258:         column_name = "(#{column_name} >> #{offset*word_size} & #{2**word_size - 1})" if offset
259:         column_name
260:       end

[Validate]