DrMark-thinking-sphinx 0.9.9 → 1.1.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README +64 -2
- data/lib/thinking_sphinx.rb +88 -11
- data/lib/thinking_sphinx/active_record.rb +136 -21
- data/lib/thinking_sphinx/active_record/delta.rb +43 -62
- data/lib/thinking_sphinx/active_record/has_many_association.rb +1 -1
- data/lib/thinking_sphinx/active_record/search.rb +7 -0
- data/lib/thinking_sphinx/adapters/abstract_adapter.rb +42 -0
- data/lib/thinking_sphinx/adapters/mysql_adapter.rb +54 -0
- data/lib/thinking_sphinx/adapters/postgresql_adapter.rb +130 -0
- data/lib/thinking_sphinx/association.rb +17 -0
- data/lib/thinking_sphinx/attribute.rb +171 -97
- data/lib/thinking_sphinx/collection.rb +126 -2
- data/lib/thinking_sphinx/configuration.rb +120 -171
- data/lib/thinking_sphinx/core/string.rb +15 -0
- data/lib/thinking_sphinx/deltas.rb +27 -0
- data/lib/thinking_sphinx/deltas/datetime_delta.rb +50 -0
- data/lib/thinking_sphinx/deltas/default_delta.rb +67 -0
- data/lib/thinking_sphinx/deltas/delayed_delta.rb +25 -0
- data/lib/thinking_sphinx/deltas/delayed_delta/delta_job.rb +24 -0
- data/lib/thinking_sphinx/deltas/delayed_delta/flag_as_deleted_job.rb +27 -0
- data/lib/thinking_sphinx/deltas/delayed_delta/job.rb +26 -0
- data/lib/thinking_sphinx/facet.rb +58 -0
- data/lib/thinking_sphinx/facet_collection.rb +60 -0
- data/lib/thinking_sphinx/field.rb +18 -52
- data/lib/thinking_sphinx/index.rb +246 -199
- data/lib/thinking_sphinx/index/builder.rb +85 -16
- data/lib/thinking_sphinx/rails_additions.rb +85 -5
- data/lib/thinking_sphinx/search.rb +459 -190
- data/lib/thinking_sphinx/tasks.rb +128 -0
- data/spec/unit/thinking_sphinx/active_record/delta_spec.rb +53 -124
- data/spec/unit/thinking_sphinx/active_record/has_many_association_spec.rb +2 -2
- data/spec/unit/thinking_sphinx/active_record_spec.rb +110 -30
- data/spec/unit/thinking_sphinx/attribute_spec.rb +16 -149
- data/spec/unit/thinking_sphinx/collection_spec.rb +14 -0
- data/spec/unit/thinking_sphinx/configuration_spec.rb +54 -412
- data/spec/unit/thinking_sphinx/core/string_spec.rb +9 -0
- data/spec/unit/thinking_sphinx/field_spec.rb +0 -79
- data/spec/unit/thinking_sphinx/index/builder_spec.rb +1 -29
- data/spec/unit/thinking_sphinx/index/faux_column_spec.rb +1 -39
- data/spec/unit/thinking_sphinx/index_spec.rb +78 -226
- data/spec/unit/thinking_sphinx/search_spec.rb +29 -228
- data/spec/unit/thinking_sphinx_spec.rb +23 -19
- data/tasks/distribution.rb +48 -0
- data/tasks/rails.rake +1 -0
- data/tasks/testing.rb +86 -0
- data/vendor/after_commit/LICENSE +20 -0
- data/vendor/after_commit/README +16 -0
- data/vendor/after_commit/Rakefile +22 -0
- data/vendor/after_commit/init.rb +8 -0
- data/vendor/after_commit/lib/after_commit.rb +45 -0
- data/vendor/after_commit/lib/after_commit/active_record.rb +114 -0
- data/vendor/after_commit/lib/after_commit/connection_adapters.rb +103 -0
- data/vendor/after_commit/test/after_commit_test.rb +53 -0
- data/vendor/delayed_job/lib/delayed/job.rb +251 -0
- data/vendor/delayed_job/lib/delayed/message_sending.rb +7 -0
- data/vendor/delayed_job/lib/delayed/performable_method.rb +55 -0
- data/vendor/delayed_job/lib/delayed/worker.rb +54 -0
- data/{lib → vendor/riddle/lib}/riddle.rb +9 -5
- data/{lib → vendor/riddle/lib}/riddle/client.rb +6 -26
- data/{lib → vendor/riddle/lib}/riddle/client/filter.rb +10 -1
- data/{lib → vendor/riddle/lib}/riddle/client/message.rb +0 -0
- data/{lib → vendor/riddle/lib}/riddle/client/response.rb +0 -0
- data/vendor/riddle/lib/riddle/configuration.rb +33 -0
- data/vendor/riddle/lib/riddle/configuration/distributed_index.rb +48 -0
- data/vendor/riddle/lib/riddle/configuration/index.rb +142 -0
- data/vendor/riddle/lib/riddle/configuration/indexer.rb +19 -0
- data/vendor/riddle/lib/riddle/configuration/remote_index.rb +17 -0
- data/vendor/riddle/lib/riddle/configuration/searchd.rb +25 -0
- data/vendor/riddle/lib/riddle/configuration/section.rb +37 -0
- data/vendor/riddle/lib/riddle/configuration/source.rb +23 -0
- data/vendor/riddle/lib/riddle/configuration/sql_source.rb +34 -0
- data/vendor/riddle/lib/riddle/configuration/xml_source.rb +28 -0
- data/vendor/riddle/lib/riddle/controller.rb +44 -0
- metadata +63 -10
- data/lib/test.rb +0 -46
- data/tasks/thinking_sphinx_tasks.rake +0 -1
- data/tasks/thinking_sphinx_tasks.rb +0 -86
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'thinking_sphinx/deltas/default_delta'
|
2
|
+
require 'thinking_sphinx/deltas/delayed_delta'
|
3
|
+
require 'thinking_sphinx/deltas/datetime_delta'
|
4
|
+
|
5
|
+
module ThinkingSphinx
|
6
|
+
module Deltas
|
7
|
+
def self.parse(index, options)
|
8
|
+
delta_option = options.delete(:delta)
|
9
|
+
case delta_option
|
10
|
+
when TrueClass, :default
|
11
|
+
DefaultDelta.new index, options
|
12
|
+
when :delayed
|
13
|
+
DelayedDelta.new index, options
|
14
|
+
when :datetime
|
15
|
+
DatetimeDelta.new index, options
|
16
|
+
when FalseClass, nil
|
17
|
+
nil
|
18
|
+
else
|
19
|
+
if delta_option.ancestors.include?(ThinkingSphinx::Deltas::DefaultDelta)
|
20
|
+
delta_option.new index, options
|
21
|
+
else
|
22
|
+
raise "Unknown delta type"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module ThinkingSphinx
|
2
|
+
module Deltas
|
3
|
+
class DatetimeDelta < ThinkingSphinx::Deltas::DefaultDelta
|
4
|
+
attr_accessor :column, :threshold
|
5
|
+
|
6
|
+
def initialize(index, options)
|
7
|
+
@index = index
|
8
|
+
@column = options.delete(:delta_column) || :updated_at
|
9
|
+
@threshold = options.delete(:threshold) || 1.day
|
10
|
+
end
|
11
|
+
|
12
|
+
def index(model, instance = nil)
|
13
|
+
# do nothing
|
14
|
+
true
|
15
|
+
end
|
16
|
+
|
17
|
+
def delayed_index(model)
|
18
|
+
config = ThinkingSphinx::Configuration.instance
|
19
|
+
rotate = ThinkingSphinx.sphinx_running? ? "--rotate" : ""
|
20
|
+
|
21
|
+
output = `#{config.bin_path}indexer --config #{config.config_file} #{rotate} #{delta_index_name model}`
|
22
|
+
output += `#{config.bin_path}indexer --config #{config.config_file} #{rotate} --merge #{core_index_name model} #{delta_index_name model} --merge-dst-range sphinx_deleted 0 0`
|
23
|
+
puts output unless ThinkingSphinx.suppress_delta_output?
|
24
|
+
|
25
|
+
true
|
26
|
+
end
|
27
|
+
|
28
|
+
def toggle(instance)
|
29
|
+
# do nothing
|
30
|
+
end
|
31
|
+
|
32
|
+
def toggled(instance)
|
33
|
+
instance.send(@column) > @threshold.ago
|
34
|
+
end
|
35
|
+
|
36
|
+
def reset_query(model)
|
37
|
+
nil
|
38
|
+
end
|
39
|
+
|
40
|
+
def clause(model, toggled)
|
41
|
+
if toggled
|
42
|
+
"#{model.quoted_table_name}.#{@index.quote_column(@column.to_s)}" +
|
43
|
+
" > #{adapter.time_difference(@threshold)}"
|
44
|
+
else
|
45
|
+
nil
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
module ThinkingSphinx
|
2
|
+
module Deltas
|
3
|
+
class DefaultDelta
|
4
|
+
attr_accessor :column
|
5
|
+
|
6
|
+
def initialize(index, options)
|
7
|
+
@index = index
|
8
|
+
@column = options.delete(:delta_column) || :delta
|
9
|
+
end
|
10
|
+
|
11
|
+
def index(model, instance = nil)
|
12
|
+
return true unless ThinkingSphinx.updates_enabled? &&
|
13
|
+
ThinkingSphinx.deltas_enabled?
|
14
|
+
return true if instance && !toggled(instance)
|
15
|
+
|
16
|
+
config = ThinkingSphinx::Configuration.instance
|
17
|
+
client = Riddle::Client.new config.address, config.port
|
18
|
+
rotate = ThinkingSphinx.sphinx_running? ? "--rotate" : ""
|
19
|
+
|
20
|
+
output = `#{config.bin_path}indexer --config #{config.config_file} #{rotate} #{delta_index_name model}`
|
21
|
+
puts(output) unless ThinkingSphinx.suppress_delta_output?
|
22
|
+
|
23
|
+
client.update(
|
24
|
+
core_index_name(model),
|
25
|
+
['sphinx_deleted'],
|
26
|
+
{instance.sphinx_document_id => [1]}
|
27
|
+
) if instance && ThinkingSphinx.sphinx_running? && instance.in_both_indexes?
|
28
|
+
|
29
|
+
true
|
30
|
+
end
|
31
|
+
|
32
|
+
def toggle(instance)
|
33
|
+
instance.delta = true
|
34
|
+
end
|
35
|
+
|
36
|
+
def toggled(instance)
|
37
|
+
instance.delta
|
38
|
+
end
|
39
|
+
|
40
|
+
def reset_query(model)
|
41
|
+
"UPDATE #{model.quoted_table_name} SET " +
|
42
|
+
"#{@index.quote_column(@column.to_s)} = #{adapter.boolean(false)}"
|
43
|
+
end
|
44
|
+
|
45
|
+
def clause(model, toggled)
|
46
|
+
"#{model.quoted_table_name}.#{@index.quote_column(@column.to_s)}" +
|
47
|
+
" = #{adapter.boolean(toggled)}"
|
48
|
+
end
|
49
|
+
|
50
|
+
protected
|
51
|
+
|
52
|
+
def core_index_name(model)
|
53
|
+
"#{model.source_of_sphinx_index.name.underscore.tr(':/\\', '_')}_core"
|
54
|
+
end
|
55
|
+
|
56
|
+
def delta_index_name(model)
|
57
|
+
"#{model.source_of_sphinx_index.name.underscore.tr(':/\\', '_')}_delta"
|
58
|
+
end
|
59
|
+
|
60
|
+
private
|
61
|
+
|
62
|
+
def adapter
|
63
|
+
@adapter = @index.model.sphinx_database_adapter
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'delayed/job'
|
2
|
+
|
3
|
+
require 'thinking_sphinx/deltas/delayed_delta/delta_job'
|
4
|
+
require 'thinking_sphinx/deltas/delayed_delta/flag_as_deleted_job'
|
5
|
+
require 'thinking_sphinx/deltas/delayed_delta/job'
|
6
|
+
|
7
|
+
module ThinkingSphinx
|
8
|
+
module Deltas
|
9
|
+
class DelayedDelta < ThinkingSphinx::Deltas::DefaultDelta
|
10
|
+
def index(model, instance = nil)
|
11
|
+
ThinkingSphinx::Deltas::Job.enqueue(
|
12
|
+
ThinkingSphinx::Deltas::DeltaJob.new(delta_index_name(model))
|
13
|
+
)
|
14
|
+
|
15
|
+
Delayed::Job.enqueue(
|
16
|
+
ThinkingSphinx::Deltas::FlagAsDeletedJob.new(
|
17
|
+
core_index_name(model), instance.sphinx_document_id
|
18
|
+
)
|
19
|
+
) if instance
|
20
|
+
|
21
|
+
true
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module ThinkingSphinx
|
2
|
+
module Deltas
|
3
|
+
class DeltaJob
|
4
|
+
attr_accessor :index
|
5
|
+
|
6
|
+
def initialize(index)
|
7
|
+
@index = index
|
8
|
+
end
|
9
|
+
|
10
|
+
def perform
|
11
|
+
return true unless ThinkingSphinx.updates_enabled? &&
|
12
|
+
ThinkingSphinx.deltas_enabled?
|
13
|
+
|
14
|
+
config = ThinkingSphinx::Configuration.instance
|
15
|
+
client = Riddle::Client.new config.address, config.port
|
16
|
+
|
17
|
+
output = `#{config.bin_path}indexer --config #{config.config_file} --rotate #{index}`
|
18
|
+
puts output unless ThinkingSphinx.suppress_delta_output?
|
19
|
+
|
20
|
+
true
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module ThinkingSphinx
|
2
|
+
module Deltas
|
3
|
+
class FlagAsDeletedJob
|
4
|
+
attr_accessor :index, :document_id
|
5
|
+
|
6
|
+
def initialize(index, document_id)
|
7
|
+
@index, @document_id = index, document_id
|
8
|
+
end
|
9
|
+
|
10
|
+
def perform
|
11
|
+
return true unless ThinkingSphinx.updates_enabled?
|
12
|
+
|
13
|
+
config = ThinkingSphinx::Configuration.instance
|
14
|
+
client = Riddle::Client.new config.address, config.port
|
15
|
+
|
16
|
+
client.update(
|
17
|
+
@index,
|
18
|
+
['sphinx_deleted'],
|
19
|
+
{@document_id => [1]}
|
20
|
+
) if ThinkingSphinx.sphinx_running? &&
|
21
|
+
ThinkingSphinx::Search.search_for_id(@document_id, @index)
|
22
|
+
|
23
|
+
true
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module ThinkingSphinx
|
2
|
+
module Deltas
|
3
|
+
class Job < Delayed::Job
|
4
|
+
def self.enqueue(object, priority = 0)
|
5
|
+
super unless duplicates_exist(object)
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.cancel_thinking_sphinx_jobs
|
9
|
+
if connection.tables.include?("delayed_jobs")
|
10
|
+
delete_all("handler LIKE '--- !ruby/object:ThinkingSphinx::Deltas::%'")
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def self.duplicates_exist(object)
|
17
|
+
count(
|
18
|
+
:conditions => {
|
19
|
+
:handler => object.to_yaml,
|
20
|
+
:locked_at => nil
|
21
|
+
}
|
22
|
+
) > 0
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
module ThinkingSphinx
|
2
|
+
class Facet
|
3
|
+
attr_reader :reference
|
4
|
+
|
5
|
+
def initialize(reference)
|
6
|
+
@reference = reference
|
7
|
+
|
8
|
+
if reference.columns.length != 1
|
9
|
+
raise "Can't translate Facets on multiple-column field or attribute"
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def name
|
14
|
+
reference.unique_name
|
15
|
+
end
|
16
|
+
|
17
|
+
def attribute_name
|
18
|
+
# @attribute_name ||= case @reference
|
19
|
+
# when Attribute
|
20
|
+
# @reference.unique_name.to_s
|
21
|
+
# when Field
|
22
|
+
@attribute_name ||= @reference.unique_name.to_s + "_facet"
|
23
|
+
# end
|
24
|
+
end
|
25
|
+
|
26
|
+
def value(object, attribute_value)
|
27
|
+
return translate(object, attribute_value) if @reference.is_a?(Field)
|
28
|
+
|
29
|
+
case @reference.type
|
30
|
+
when :string
|
31
|
+
translate(object, attribute_value)
|
32
|
+
when :datetime
|
33
|
+
Time.at(attribute_value)
|
34
|
+
when :boolean
|
35
|
+
attribute_value > 0
|
36
|
+
else
|
37
|
+
attribute_value
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def to_s
|
42
|
+
name
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
def translate(object, attribute_value)
|
48
|
+
column.__stack.each { |method|
|
49
|
+
object = object.send(method)
|
50
|
+
}
|
51
|
+
object.send(column.__name)
|
52
|
+
end
|
53
|
+
|
54
|
+
def column
|
55
|
+
@reference.columns.first
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
module ThinkingSphinx
|
2
|
+
class FacetCollection < Hash
|
3
|
+
attr_accessor :arguments
|
4
|
+
|
5
|
+
def initialize(arguments)
|
6
|
+
@arguments = arguments.clone
|
7
|
+
@attribute_values = {}
|
8
|
+
@facets = []
|
9
|
+
end
|
10
|
+
|
11
|
+
def add_from_results(facet, results)
|
12
|
+
facet = facet_from_object(results.first, facet) if facet.is_a?(String)
|
13
|
+
|
14
|
+
self[facet.name] ||= {}
|
15
|
+
@attribute_values[facet.name] ||= {}
|
16
|
+
@facets << facet
|
17
|
+
|
18
|
+
results.each_with_groupby_and_count { |result, group, count|
|
19
|
+
facet_value = facet.value(result, group)
|
20
|
+
|
21
|
+
self[facet.name][facet_value] ||= 0
|
22
|
+
self[facet.name][facet_value] += count
|
23
|
+
@attribute_values[facet.name][facet_value] = group
|
24
|
+
}
|
25
|
+
end
|
26
|
+
|
27
|
+
def for(hash = {})
|
28
|
+
arguments = @arguments.clone
|
29
|
+
options = arguments.extract_options!
|
30
|
+
options[:with] ||= {}
|
31
|
+
|
32
|
+
hash.each do |key, value|
|
33
|
+
attrib = facet_for_key(key).attribute_name
|
34
|
+
options[:with][attrib] = underlying_value key, value
|
35
|
+
end
|
36
|
+
|
37
|
+
arguments << options
|
38
|
+
ThinkingSphinx::Search.search *arguments
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def underlying_value(key, value)
|
44
|
+
case value
|
45
|
+
when Array
|
46
|
+
value.collect { |item| underlying_value(key, item) }
|
47
|
+
else
|
48
|
+
@attribute_values[key][value]
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def facet_for_key(key)
|
53
|
+
@facets.detect { |facet| facet.name == key }
|
54
|
+
end
|
55
|
+
|
56
|
+
def facet_from_object(object, name)
|
57
|
+
object.sphinx_facets.detect { |facet| facet.attribute_name == name }
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -8,7 +8,8 @@ module ThinkingSphinx
|
|
8
8
|
# associations. Which can get messy. Use Index.link!, it really helps.
|
9
9
|
#
|
10
10
|
class Field
|
11
|
-
attr_accessor :alias, :columns, :sortable, :associations, :model, :infixes,
|
11
|
+
attr_accessor :alias, :columns, :sortable, :associations, :model, :infixes,
|
12
|
+
:prefixes, :faceted
|
12
13
|
|
13
14
|
# To create a new field, you'll need to pass in either a single Column
|
14
15
|
# or an array of them, and some (optional) options. The columns are
|
@@ -58,10 +59,11 @@ module ThinkingSphinx
|
|
58
59
|
|
59
60
|
raise "Cannot define a field with no columns. Maybe you are trying to index a field with a reserved name (id, name). You can fix this error by using a symbol rather than a bare name (:id instead of id)." if @columns.empty? || @columns.any? { |column| !column.respond_to?(:__stack) }
|
60
61
|
|
61
|
-
@alias
|
62
|
-
@sortable
|
63
|
-
@infixes
|
64
|
-
@prefixes
|
62
|
+
@alias = options[:as]
|
63
|
+
@sortable = options[:sortable] || false
|
64
|
+
@infixes = options[:infixes] || false
|
65
|
+
@prefixes = options[:prefixes] || false
|
66
|
+
@faceted = options[:facet] || false
|
65
67
|
end
|
66
68
|
|
67
69
|
# Get the part of the SELECT clause related to this field. Don't forget
|
@@ -75,10 +77,10 @@ module ThinkingSphinx
|
|
75
77
|
column_with_prefix(column)
|
76
78
|
}.join(', ')
|
77
79
|
|
78
|
-
clause = concatenate(clause) if concat_ws?
|
79
|
-
clause = group_concatenate(clause) if is_many?
|
80
|
+
clause = adapter.concatenate(clause) if concat_ws?
|
81
|
+
clause = adapter.group_concatenate(clause) if is_many?
|
80
82
|
|
81
|
-
"#{cast_to_string clause } AS #{quote_column(unique_name)}"
|
83
|
+
"#{adapter.cast_to_string clause } AS #{quote_column(unique_name)}"
|
82
84
|
end
|
83
85
|
|
84
86
|
# Get the part of the GROUP BY clause related to this field - if one is
|
@@ -110,39 +112,16 @@ module ThinkingSphinx
|
|
110
112
|
end
|
111
113
|
end
|
112
114
|
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
when "ActiveRecord::ConnectionAdapters::MysqlAdapter"
|
118
|
-
"CONCAT_WS(' ', #{clause})"
|
119
|
-
when "ActiveRecord::ConnectionAdapters::PostgreSQLAdapter"
|
120
|
-
clause.split(', ').join(" || ' ' || ")
|
121
|
-
else
|
122
|
-
clause
|
123
|
-
end
|
115
|
+
def to_facet
|
116
|
+
return nil unless @faceted
|
117
|
+
|
118
|
+
ThinkingSphinx::Facet.new(self)
|
124
119
|
end
|
125
120
|
|
126
|
-
|
127
|
-
case @model.connection.class.name
|
128
|
-
when "ActiveRecord::ConnectionAdapters::MysqlAdapter"
|
129
|
-
"GROUP_CONCAT(#{clause} SEPARATOR ' ')"
|
130
|
-
when "ActiveRecord::ConnectionAdapters::PostgreSQLAdapter"
|
131
|
-
"array_to_string(array_accum(#{clause}), ' ')"
|
132
|
-
else
|
133
|
-
clause
|
134
|
-
end
|
135
|
-
end
|
121
|
+
private
|
136
122
|
|
137
|
-
def
|
138
|
-
|
139
|
-
when "ActiveRecord::ConnectionAdapters::MysqlAdapter"
|
140
|
-
"CAST(#{clause} AS CHAR)"
|
141
|
-
when "ActiveRecord::ConnectionAdapters::PostgreSQLAdapter"
|
142
|
-
clause
|
143
|
-
else
|
144
|
-
clause
|
145
|
-
end
|
123
|
+
def adapter
|
124
|
+
@adapter ||= @model.sphinx_database_adapter
|
146
125
|
end
|
147
126
|
|
148
127
|
def quote_column(column)
|
@@ -156,16 +135,7 @@ module ThinkingSphinx
|
|
156
135
|
def concat_ws?
|
157
136
|
@columns.length > 1 || multiple_associations?
|
158
137
|
end
|
159
|
-
|
160
|
-
# Checks the association tree for each column - if they're all the same,
|
161
|
-
# returns false.
|
162
|
-
#
|
163
|
-
def multiple_sources?
|
164
|
-
first = associations[@columns.first]
|
165
|
-
|
166
|
-
!@columns.all? { |col| associations[col] == first }
|
167
|
-
end
|
168
|
-
|
138
|
+
|
169
139
|
# Checks whether any column requires multiple associations (which only
|
170
140
|
# happens for polymorphic situations).
|
171
141
|
#
|
@@ -198,9 +168,5 @@ module ThinkingSphinx
|
|
198
168
|
def is_many?
|
199
169
|
associations.values.flatten.any? { |assoc| assoc.is_many? }
|
200
170
|
end
|
201
|
-
|
202
|
-
def is_string?
|
203
|
-
columns.all? { |col| col.is_string? }
|
204
|
-
end
|
205
171
|
end
|
206
172
|
end
|