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 270
270:       def construct_join_sql(key_relation, num )
271:         join_sql = ""
272:         connection = klass.connection
273:         key = key_relation.to_s.singularize.to_sym
274:         main = definition.klass.to_s.gsub(/.*::/,'').underscore.to_sym
275: 
276:         key_table = klass.reflections[key].table_name
277:         key_table_pk = klass.reflections[key].klass.primary_key
278: 
279:         value_table = klass.table_name.to_s
280:         value_table_fk_key = klass.reflections[key].association_foreign_key
281: 
282:         if klass.reflections[main]
283:           main_table = definition.klass.table_name
284:           main_table_pk = klass.reflections[main].klass.primary_key
285:           value_table_fk_main = klass.reflections[main].association_foreign_key
286: 
287:           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})"
288:           value_table = " #{value_table}_#{num}"
289:         end
290:         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}) "
291: 
292:         return join_sql
293:       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 304
304:       def construct_simple_join_sql( num )
305:         connection = klass.connection
306:         main = definition.klass.to_s.gsub(/.*::/,'').underscore.to_sym
307:         key_value_table = klass.table_name
308: 
309:         main_table = definition.klass.table_name
310:         main_table_pk = klass.reflections[main].klass.primary_key
311:         value_table_fk_main = klass.reflections[main].options[:foreign_key]
312:         value_table_fk_main ||= klass.reflections[main].association_foreign_key
313: 
314:         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})"
315:         return join_sql
316:       end

[Source]

     # File lib/scoped_search/query_builder.rb, line 318
318:       def to_ext_method_sql(key, operator, value, &block)
319:         raise ScopedSearch::QueryNotSupported, "'#{definition.klass}' doesn't respond to '#{ext_method}'" unless definition.klass.respond_to?(ext_method)
320:         conditions = definition.klass.send(ext_method.to_sym,key, operator, value) rescue {}
321:         raise ScopedSearch::QueryNotSupported, "external method '#{ext_method}' should return hash" unless conditions.kind_of?(Hash)
322:         sql = ''
323:         conditions.map do |notification, content|
324:           case notification
325:             when :include then yield(:include, content)
326:             when :joins then yield(:joins, content)
327:             when :conditions then sql = content
328:             when :parameter then content.map{|c| yield(:parameter, c)}
329:           end
330:         end
331:         return sql
332:       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 240
240:       def to_sql(operator = nil, &block) # :yields: finder_option_type, value
241:         num = rand(1000000)
242:         connection = klass.connection
243:         if key_relation
244:           yield(:joins, construct_join_sql(key_relation, num) )
245:           yield(:keycondition, "#{key_klass.table_name}_#{num}.#{connection.quote_column_name(key_field.to_s)} = ?")
246:           klass_table_name = relation ? "#{klass.table_name}_#{num}" : connection.quote_table_name(klass.table_name)
247:           return "#{klass_table_name}.#{connection.quote_column_name(field.to_s)}"
248:         elsif key_field
249:           yield(:joins, construct_simple_join_sql(num))
250:           yield(:keycondition, "#{key_klass.table_name}_#{num}.#{connection.quote_column_name(key_field.to_s)} = ?")
251:           klass_table_name = relation ? "#{klass.table_name}_#{num}" : connection.quote_table_name(klass.table_name)
252:           return "#{klass_table_name}.#{connection.quote_column_name(field.to_s)}"
253:         elsif relation
254:           yield(:include, relation)
255:         end
256:         column_name = connection.quote_table_name(klass.table_name.to_s) + "." + connection.quote_column_name(field.to_s)
257:         column_name = "(#{column_name} >> #{offset*word_size} & #{2**word_size - 1})" if offset
258:         column_name
259:       end

[Validate]