lib/thinking_sphinx/attribute.rb in ebeigarts-thinking-sphinx-1.1.22 vs lib/thinking_sphinx/attribute.rb in ebeigarts-thinking-sphinx-1.2.10

- old
+ new

@@ -73,11 +73,13 @@ @type = options[:type] @query_source = options[:source] @crc = options[:crc] @type ||= :multi unless @query_source.nil? - @type = :integer if @type == :string && @crc + if @type == :string && @crc + @type = is_many? ? :multi : :integer + end source.attributes << self end # Get the part of the SELECT clause related to this attribute. Don't forget @@ -87,18 +89,25 @@ # datetimes to timestamps, as needed. # def to_select_sql return nil unless include_as_association? - separator = all_ints? || @crc ? ',' : ' ' + separator = all_ints? || all_datetimes? || @crc ? ',' : ' ' clause = @columns.collect { |column| part = column_with_prefix(column) - type == :string ? adapter.convert_nulls(part) : part + case type + when :string + adapter.convert_nulls(part) + when :datetime + adapter.cast_to_datetime(part) + else + part + end }.join(', ') - clause = adapter.cast_to_datetime(clause) if type == :datetime + # clause = adapter.cast_to_datetime(clause) if type == :datetime clause = adapter.crc(clause) if @crc clause = adapter.concatenate(clause, separator) if concat_ws? clause = adapter.group_concatenate(clause, separator) if is_many? "#{clause} AS #{quote_column(unique_name)}" @@ -123,14 +132,14 @@ # Returns the configuration value that should be used for # the attribute. # Special case is the multi-valued attribute that needs some # extra configuration. # - def config_value(offset = nil) + def config_value(offset = nil, delta = false) if type == :multi && ThinkingSphinx::Configuration.instance.type != "xml" multi_config = include_as_association? ? "field" : - source_value(offset).gsub(/\s+/m, " ").strip + source_value(offset, delta).gsub(/\s+/m, " ").strip "uint #{unique_name} from #{multi_config}" else unique_name end end @@ -141,10 +150,12 @@ # actual column's datatype is and returns that. # def type @type ||= begin base_type = case + when is_many_datetimes? + :datetime when is_many?, is_many_ints? :multi when @associations.values.flatten.length > 1 :string else @@ -170,29 +181,33 @@ column.__stack.each { |method| object = object.send(method) } object.send(column.__name) end def all_ints? - @columns.all? { |col| - klasses = @associations[col].empty? ? [@model] : - @associations[col].collect { |assoc| assoc.reflection.klass } - klasses.all? { |klass| - column = klass.columns.detect { |column| column.name == col.__name.to_s } - !column.nil? && column.type == :integer - } - } + all_of_type?(:integer) end + def all_datetimes? + all_of_type?(:datetime, :date, :timestamp) + end + private - def source_value(offset) + def source_value(offset, delta) if is_string? - "#{query_source.to_s.dasherize}; #{columns.first.__name}" - elsif query_source == :ranged_query - "ranged-query; #{query offset} #{query_clause}; #{range_query}" + return "#{query_source.to_s.dasherize}; #{columns.first.__name}" + end + + query = query(offset) + + if query_source == :ranged_query + query += query_clause + query += " AND #{query_delta.strip}" if delta + "ranged-query; #{query}; #{range_query}" else - "query; #{query offset}" + query += "WHERE #{query_delta.strip}" if delta + "query; #{query}" end end def query(offset) base_assoc = base_association_for_mva @@ -210,10 +225,19 @@ def query_clause foreign_key = foreign_key_for_mva base_association_for_mva "WHERE #{foreign_key} >= $start AND #{foreign_key} <= $end" end + def query_delta + foreign_key = foreign_key_for_mva base_association_for_mva + <<-SQL +#{foreign_key} IN (SELECT #{quote_column model.primary_key} +FROM #{model.quoted_table_name} +WHERE #{@source.index.delta_object.clause(model, true)}) + SQL + end + def range_query assoc = base_association_for_mva foreign_key = foreign_key_for_mva assoc "SELECT MIN(#{foreign_key}), MAX(#{foreign_key}) FROM #{quote_table_name assoc.table}" end @@ -257,18 +281,23 @@ end def is_many_ints? concat_ws? && all_ints? end - + + def is_many_datetimes? + is_many? && all_datetimes? + end + def type_from_database klass = @associations.values.flatten.first ? @associations.values.flatten.first.reflection.klass : @model - klass.columns.detect { |col| + column = klass.columns.detect { |col| @columns.collect { |c| c.__name.to_s }.include? col.name - }.type + } + column.nil? ? nil : column.type end def translated_type_from_database case type_from_db = type_from_database when :datetime, :string, :float, :boolean, :integer @@ -285,8 +314,19 @@ You could try to explicitly convert the column's value in your define_index block: has "CAST(column AS INT)", :type => :integer, :as => :column MESSAGE end + end + + def all_of_type?(*column_types) + @columns.all? { |col| + klasses = @associations[col].empty? ? [@model] : + @associations[col].collect { |assoc| assoc.reflection.klass } + klasses.all? { |klass| + column = klass.columns.detect { |column| column.name == col.__name.to_s } + !column.nil? && column_types.include?(column.type) + } + } end end end \ No newline at end of file