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 259
259:       def construct_join_sql(key_relation, num )
260:         join_sql = ""
261:         connection = klass.connection
262:         key = key_relation.to_s.singularize.to_sym
263:         main = definition.klass.to_s.gsub(/.*::/,'').underscore.to_sym
264: 
265:         key_table = klass.reflections[key].table_name
266:         key_table_pk = klass.reflections[key].klass.primary_key
267: 
268:         value_table = klass.table_name.to_s
269:         value_table_fk_key = klass.reflections[key].association_foreign_key
270: 
271:         if klass.reflections[main]
272:           main_table = definition.klass.table_name
273:           main_table_pk = klass.reflections[main].klass.primary_key
274:           value_table_fk_main = klass.reflections[main].association_foreign_key
275: 
276:           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})"
277:           value_table = " #{value_table}_#{num}"
278:         end
279:         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}) "
280: 
281:         return join_sql
282:       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 293
293:       def construct_simple_join_sql( num )
294:         connection = klass.connection
295:         main = definition.klass.to_s.gsub(/.*::/,'').underscore.to_sym
296:         key_value_table = klass.table_name
297: 
298:         main_table = definition.klass.table_name
299:         main_table_pk = klass.reflections[main].klass.primary_key
300:         value_table_fk_main = klass.reflections[main].options[:foreign_key]
301:         value_table_fk_main ||= klass.reflections[main].association_foreign_key
302: 
303:         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})"
304:         return join_sql
305:       end

[Source]

     # File lib/scoped_search/query_builder.rb, line 307
307:       def to_ext_method_sql(key, operator, value, &block)
308:         raise ScopedSearch::QueryNotSupported, "'#{definition.klass}' doesn't respond to '#{ext_method}'" unless definition.klass.respond_to?(ext_method)
309:         conditions = definition.klass.send(ext_method.to_sym,key, operator, value) rescue {}
310:         raise ScopedSearch::QueryNotSupported, "external method '#{ext_method}' should return hash" unless conditions.kind_of?(Hash)
311:         sql = ''
312:         conditions.map do |notification, content|
313:           case notification
314:             when :include then yield(:include, content)
315:             when :joins then yield(:joins, content)
316:             when :conditions then sql = content
317:             when :parameter then content.map{|c| yield(:parameter, c)}
318:           end
319:         end
320:         return sql
321:       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 229
229:       def to_sql(operator = nil, &block) # :yields: finder_option_type, value
230:         num = rand(1000000)
231:         connection = klass.connection
232:         if key_relation
233:           yield(:joins, construct_join_sql(key_relation, num) )
234:           yield(:keycondition, "#{key_klass.table_name}_#{num}.#{connection.quote_column_name(key_field.to_s)} = ?")
235:           klass_table_name = relation ? "#{klass.table_name}_#{num}" : connection.quote_table_name(klass.table_name)
236:           return "#{klass_table_name}.#{connection.quote_column_name(field.to_s)}"
237:         elsif key_field
238:           yield(:joins, construct_simple_join_sql(num))
239:           yield(:keycondition, "#{key_klass.table_name}_#{num}.#{connection.quote_column_name(key_field.to_s)} = ?")
240:           klass_table_name = relation ? "#{klass.table_name}_#{num}" : connection.quote_table_name(klass.table_name)
241:           return "#{klass_table_name}.#{connection.quote_column_name(field.to_s)}"
242:         elsif relation
243:           yield(:include, relation)
244:         end
245:         column_name = connection.quote_table_name(klass.table_name.to_s) + "." + connection.quote_column_name(field.to_s)
246:         column_name = "(#{column_name} >> #{offset*word_size} & #{2**word_size - 1})" if offset
247:         column_name
248:       end

[Validate]