thinking-sphinx 3.0.3 → 3.0.4
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.
- checksums.yaml +7 -0
- data/.gitignore +2 -1
- data/HISTORY +25 -0
- data/lib/thinking_sphinx.rb +1 -0
- data/lib/thinking_sphinx/active_record/association_proxy.rb +13 -55
- data/lib/thinking_sphinx/active_record/association_proxy/attribute_finder.rb +47 -0
- data/lib/thinking_sphinx/active_record/base.rb +16 -15
- data/lib/thinking_sphinx/active_record/callbacks/delete_callbacks.rb +1 -12
- data/lib/thinking_sphinx/active_record/database_adapters.rb +41 -42
- data/lib/thinking_sphinx/active_record/polymorpher.rb +7 -2
- data/lib/thinking_sphinx/active_record/property_query.rb +23 -19
- data/lib/thinking_sphinx/active_record/sql_builder.rb +108 -129
- data/lib/thinking_sphinx/active_record/sql_builder/clause_builder.rb +28 -0
- data/lib/thinking_sphinx/active_record/sql_builder/query.rb +43 -0
- data/lib/thinking_sphinx/active_record/sql_builder/statement.rb +110 -0
- data/lib/thinking_sphinx/active_record/sql_source.rb +143 -138
- data/lib/thinking_sphinx/capistrano.rb +11 -8
- data/lib/thinking_sphinx/configuration.rb +57 -35
- data/lib/thinking_sphinx/connection.rb +15 -6
- data/lib/thinking_sphinx/core.rb +1 -0
- data/lib/thinking_sphinx/core/index.rb +18 -10
- data/lib/thinking_sphinx/core/settings.rb +9 -0
- data/lib/thinking_sphinx/deletion.rb +48 -0
- data/lib/thinking_sphinx/errors.rb +7 -0
- data/lib/thinking_sphinx/excerpter.rb +1 -0
- data/lib/thinking_sphinx/facet_search.rb +42 -19
- data/lib/thinking_sphinx/masks/scopes_mask.rb +7 -0
- data/lib/thinking_sphinx/middlewares.rb +27 -33
- data/lib/thinking_sphinx/middlewares/active_record_translator.rb +18 -18
- data/lib/thinking_sphinx/middlewares/geographer.rb +49 -16
- data/lib/thinking_sphinx/middlewares/sphinxql.rb +128 -58
- data/lib/thinking_sphinx/panes/excerpts_pane.rb +7 -3
- data/lib/thinking_sphinx/rake_interface.rb +10 -0
- data/lib/thinking_sphinx/real_time.rb +7 -1
- data/lib/thinking_sphinx/real_time/attribute.rb +4 -0
- data/lib/thinking_sphinx/real_time/callbacks/real_time_callbacks.rb +14 -10
- data/lib/thinking_sphinx/real_time/index.rb +20 -12
- data/lib/thinking_sphinx/search/glaze.rb +5 -0
- data/lib/thinking_sphinx/search/query.rb +4 -8
- data/lib/thinking_sphinx/tasks.rb +8 -0
- data/spec/acceptance/excerpts_spec.rb +22 -0
- data/spec/acceptance/remove_deleted_records_spec.rb +10 -0
- data/spec/acceptance/searching_across_models_spec.rb +10 -0
- data/spec/acceptance/searching_with_filters_spec.rb +15 -0
- data/spec/acceptance/specifying_sql_spec.rb +3 -3
- data/spec/acceptance/sphinx_scopes_spec.rb +11 -0
- data/spec/internal/app/indices/product_index.rb +2 -0
- data/spec/internal/app/models/categorisation.rb +6 -0
- data/spec/internal/app/models/category.rb +3 -0
- data/spec/internal/app/models/product.rb +4 -1
- data/spec/internal/db/schema.rb +10 -0
- data/spec/thinking_sphinx/active_record/base_spec.rb +33 -0
- data/spec/thinking_sphinx/active_record/callbacks/delete_callbacks_spec.rb +4 -35
- data/spec/thinking_sphinx/active_record/sql_builder_spec.rb +5 -10
- data/spec/thinking_sphinx/active_record/sql_source_spec.rb +4 -3
- data/spec/thinking_sphinx/configuration_spec.rb +26 -6
- data/spec/thinking_sphinx/connection_spec.rb +4 -1
- data/spec/thinking_sphinx/deletion_spec.rb +76 -0
- data/spec/thinking_sphinx/facet_search_spec.rb +54 -5
- data/spec/thinking_sphinx/panes/excerpts_pane_spec.rb +4 -6
- data/spec/thinking_sphinx/rake_interface_spec.rb +35 -0
- data/spec/thinking_sphinx/real_time/callbacks/real_time_callbacks_spec.rb +68 -28
- data/spec/thinking_sphinx/search/glaze_spec.rb +19 -0
- data/spec/thinking_sphinx/search/query_spec.rb +39 -2
- data/thinking-sphinx.gemspec +2 -2
- metadata +31 -45
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: e4abfc7a0ce650e92e51a842336ec1028f12e9ea
|
4
|
+
data.tar.gz: 2c51520fcd002486f51e127f981f5e7c60000706
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 384ba739298c2dc12431cf9c74e79a3f15191098d84b41afab0e94383ac9403384e9290e38c834ef17a1675eedf5835477f63c12aeeb440144421dab97e82959
|
7
|
+
data.tar.gz: 787f2a640087f91d7ffd7d39d1b092fb027551e6df58d2ab19062a78bfebe3b7bbbfe8ad4c65858d84fc590403eb0515296c6a5192fc3aaf6937e2f595b1ec3a
|
data/.gitignore
CHANGED
data/HISTORY
CHANGED
@@ -1,3 +1,28 @@
|
|
1
|
+
2013-07-09: 3.0.4
|
2
|
+
* [CHANGE] Updating Riddle dependency to be >= 1.5.7.
|
3
|
+
* [FEATURE] ts:regenerate rake task for rebuilding Sphinx when realtime indices are involved.
|
4
|
+
* [FEATURE] ts:clear task removes all Sphinx index and binlog files.
|
5
|
+
* [CHANGE] Glaze now responds to respond_to? (@groe).
|
6
|
+
* [FEATURE] Facet search calls now respect the limit option (which otherwise defaults to max_matches) (Demian Ferreiro).
|
7
|
+
* [FEATURE] Excerpts words can be overwritten with the words option (@groe).
|
8
|
+
* [FIX] Empty queries with the star option set to true are handled gracefully.
|
9
|
+
* [CHANGE] Deleted ActiveRecord objects are deleted in realtime indices as well.
|
10
|
+
* [CHANGE] Realtime callbacks are no longer automatically added, but they're now more flexible (for association situations).
|
11
|
+
* [CHANGE] Cleaning and refactoring so Code Climate ranks this as A-level code (Philip Arndt, Shevaun Coker, Garrett Heinlen).
|
12
|
+
* [FIX] Excerpts are now wildcard-friendly.
|
13
|
+
* [FIX] Facet searches now use max_matches value (with a default of 1000) to ensure as many results as possible are returned.
|
14
|
+
* [CHANGE] Exceptions raised when communicating with Sphinx are now mentioned in the logs when queries are retried (instead of STDOUT).
|
15
|
+
* [CHANGE] Excerpts now use just the query and standard conditions, instead of parsing Sphinx's keyword metadata (which had model names in it).
|
16
|
+
* [FIX] The settings cache is now cleared when the configuration singleton is reset (Pedro Cunha).
|
17
|
+
* [FEATURE] The :facets option can be used in facet searches to limit which facets are queried.
|
18
|
+
* [FIX] Escaped @'s in queries are considered part of each word, instead of word separators.
|
19
|
+
* [FIX] Internal class name conditions are ignored with auto-starred queries.
|
20
|
+
* [FEATURE] A separate role can be set for Sphinx actions with Capistrano (Andrey Chernih).
|
21
|
+
* [FIX] RDoc doesn't like constant hierarchies split over multiple lines.
|
22
|
+
* [CHANGE] Get database connection details from ActiveRecord::Base, not each model, as this is where changes are reflected.
|
23
|
+
* [CHANGE] Default Sphinx scopes are applied to new facet searches.
|
24
|
+
* [FEATURE] Facet searches can now be called from Sphinx scopes.
|
25
|
+
|
1
26
|
2013-05-07: 3.0.3
|
2
27
|
* [CHANGE] Updating Riddle dependency to be >= 1.5.6
|
3
28
|
* [FEATURE] INDEX_ONLY environment flag is passed through when invoked through Capistrano (Demian Ferreiro).
|
data/lib/thinking_sphinx.rb
CHANGED
@@ -42,6 +42,7 @@ require 'thinking_sphinx/callbacks'
|
|
42
42
|
require 'thinking_sphinx/core'
|
43
43
|
require 'thinking_sphinx/configuration'
|
44
44
|
require 'thinking_sphinx/connection'
|
45
|
+
require 'thinking_sphinx/deletion'
|
45
46
|
require 'thinking_sphinx/errors'
|
46
47
|
require 'thinking_sphinx/excerpter'
|
47
48
|
require 'thinking_sphinx/facet'
|
@@ -2,73 +2,31 @@ module ThinkingSphinx::ActiveRecord::AssociationProxy
|
|
2
2
|
extend ActiveSupport::Concern
|
3
3
|
|
4
4
|
def search(query = nil, options = {})
|
5
|
-
query, options
|
6
|
-
options[:ignore_scopes] = true
|
7
|
-
|
8
|
-
ThinkingSphinx::Search::Merger.new(super).merge! nil,
|
9
|
-
:with => association_filter
|
5
|
+
perform_search super(*normalise_search_arguments(query, options))
|
10
6
|
end
|
11
7
|
|
12
8
|
def search_for_ids(query = nil, options = {})
|
9
|
+
perform_search super(*normalise_search_arguments(query, options))
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
def normalise_search_arguments(query, options)
|
13
14
|
query, options = nil, query if query.is_a?(Hash)
|
14
15
|
options[:ignore_scopes] = true
|
15
16
|
|
16
|
-
|
17
|
-
:with => association_filter
|
17
|
+
[query, options]
|
18
18
|
end
|
19
19
|
|
20
|
-
|
20
|
+
def perform_search(searcher)
|
21
|
+
ThinkingSphinx::Search::Merger.new(searcher).merge! nil,
|
22
|
+
:with => association_filter
|
23
|
+
end
|
21
24
|
|
22
25
|
def association_filter
|
23
26
|
attribute = AttributeFinder.new(proxy_association).attribute
|
24
27
|
|
25
28
|
{attribute.name.to_sym => proxy_association.owner.id}
|
26
29
|
end
|
27
|
-
|
28
|
-
class AttributeFinder
|
29
|
-
def initialize(association)
|
30
|
-
@association = association
|
31
|
-
end
|
32
|
-
|
33
|
-
def attribute
|
34
|
-
attributes.detect { |attribute|
|
35
|
-
# Don't bother with attributes built from multiple columns
|
36
|
-
next unless attribute.columns.length == 1
|
37
|
-
|
38
|
-
attribute.columns.first.__name == foreign_key.to_sym ||
|
39
|
-
attribute.name == foreign_key.to_s
|
40
|
-
} or raise "Missing Attribute for Foreign Key #{foreign_key}"
|
41
|
-
end
|
42
|
-
|
43
|
-
private
|
44
|
-
|
45
|
-
def attributes
|
46
|
-
sources.collect(&:attributes).flatten
|
47
|
-
end
|
48
|
-
|
49
|
-
def configuration
|
50
|
-
ThinkingSphinx::Configuration.instance
|
51
|
-
end
|
52
|
-
|
53
|
-
def foreign_key
|
54
|
-
@foreign_key ||= if @association.reflection.through_reflection
|
55
|
-
@association.reflection.through_reflection.foreign_key
|
56
|
-
else
|
57
|
-
@association.reflection.foreign_key
|
58
|
-
end
|
59
|
-
end
|
60
|
-
|
61
|
-
def indices
|
62
|
-
@indices ||= begin
|
63
|
-
configuration.preload_indices
|
64
|
-
configuration.indices_for_references(
|
65
|
-
*@association.klass.name.underscore.to_sym
|
66
|
-
)
|
67
|
-
end
|
68
|
-
end
|
69
|
-
|
70
|
-
def sources
|
71
|
-
indices.collect(&:sources).flatten
|
72
|
-
end
|
73
|
-
end
|
74
30
|
end
|
31
|
+
|
32
|
+
require 'thinking_sphinx/active_record/association_proxy/attribute_finder'
|
@@ -0,0 +1,47 @@
|
|
1
|
+
class ThinkingSphinx::ActiveRecord::AssociationProxy::AttributeFinder
|
2
|
+
def initialize(association)
|
3
|
+
@association = association
|
4
|
+
end
|
5
|
+
|
6
|
+
def attribute
|
7
|
+
attributes.detect { |attribute|
|
8
|
+
# Don't bother with attributes built from multiple columns
|
9
|
+
next if attribute.columns.many?
|
10
|
+
|
11
|
+
attribute.columns.first.__name == foreign_key.to_sym ||
|
12
|
+
attribute.name == foreign_key.to_s
|
13
|
+
} or raise "Missing Attribute for Foreign Key #{foreign_key}"
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
def attributes
|
18
|
+
sources.collect(&:attributes).flatten
|
19
|
+
end
|
20
|
+
|
21
|
+
def configuration
|
22
|
+
ThinkingSphinx::Configuration.instance
|
23
|
+
end
|
24
|
+
|
25
|
+
def foreign_key
|
26
|
+
@foreign_key ||= reflection_target.foreign_key
|
27
|
+
end
|
28
|
+
|
29
|
+
def indices
|
30
|
+
@indices ||= begin
|
31
|
+
configuration.preload_indices
|
32
|
+
configuration.indices_for_references(
|
33
|
+
*@association.klass.name.underscore.to_sym
|
34
|
+
)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def reflection_target
|
39
|
+
target = @association.reflection
|
40
|
+
target = target.through_reflection if target.through_reflection
|
41
|
+
target
|
42
|
+
end
|
43
|
+
|
44
|
+
def sources
|
45
|
+
indices.collect(&:sources).flatten
|
46
|
+
end
|
47
|
+
end
|
@@ -7,30 +7,17 @@ module ThinkingSphinx::ActiveRecord::Base
|
|
7
7
|
after_update ThinkingSphinx::ActiveRecord::Callbacks::UpdateCallbacks
|
8
8
|
after_commit ThinkingSphinx::ActiveRecord::Callbacks::DeltaCallbacks
|
9
9
|
|
10
|
-
after_save ThinkingSphinx::RealTime::Callbacks::RealTimeCallbacks
|
11
|
-
|
12
10
|
::ActiveRecord::Associations::CollectionProxy.send :include,
|
13
11
|
ThinkingSphinx::ActiveRecord::AssociationProxy
|
14
12
|
end
|
15
13
|
|
16
14
|
module ClassMethods
|
17
15
|
def facets(query = nil, options = {})
|
18
|
-
|
19
|
-
ThinkingSphinx::Search::Merger.new(search).merge! nil, :classes => [self]
|
16
|
+
merge_search ThinkingSphinx.facets, query, options
|
20
17
|
end
|
21
18
|
|
22
19
|
def search(query = nil, options = {})
|
23
|
-
|
24
|
-
|
25
|
-
merger.merge! *default_sphinx_scope_response if default_sphinx_scope?
|
26
|
-
merger.merge! query, options
|
27
|
-
|
28
|
-
if current_scope && !merger.search.options[:ignore_scopes]
|
29
|
-
raise ThinkingSphinx::MixedScopesError,
|
30
|
-
'You cannot search with Sphinx through ActiveRecord scopes'
|
31
|
-
end
|
32
|
-
|
33
|
-
merger.merge! nil, :classes => [self]
|
20
|
+
merge_search ThinkingSphinx.search, query, options
|
34
21
|
end
|
35
22
|
|
36
23
|
def search_count(query = nil, options = {})
|
@@ -51,5 +38,19 @@ module ThinkingSphinx::ActiveRecord::Base
|
|
51
38
|
def default_sphinx_scope_response
|
52
39
|
[sphinx_scopes[default_sphinx_scope].call].flatten
|
53
40
|
end
|
41
|
+
|
42
|
+
def merge_search(search, query, options)
|
43
|
+
merger = ThinkingSphinx::Search::Merger.new search
|
44
|
+
|
45
|
+
merger.merge! *default_sphinx_scope_response if default_sphinx_scope?
|
46
|
+
merger.merge! query, options
|
47
|
+
|
48
|
+
if current_scope && !merger.search.options[:ignore_scopes]
|
49
|
+
raise ThinkingSphinx::MixedScopesError,
|
50
|
+
'You cannot search with Sphinx through ActiveRecord scopes'
|
51
|
+
end
|
52
|
+
|
53
|
+
merger.merge! nil, :classes => [self]
|
54
|
+
end
|
54
55
|
end
|
55
56
|
end
|
@@ -4,14 +4,7 @@ class ThinkingSphinx::ActiveRecord::Callbacks::DeleteCallbacks <
|
|
4
4
|
callbacks :after_destroy
|
5
5
|
|
6
6
|
def after_destroy
|
7
|
-
indices.each
|
8
|
-
connection.execute Riddle::Query.update(
|
9
|
-
index.name, index.document_id_for_key(instance.id),
|
10
|
-
:sphinx_deleted => true
|
11
|
-
)
|
12
|
-
end
|
13
|
-
rescue Mysql2::Error => error
|
14
|
-
# This isn't vital, so don't raise the error.
|
7
|
+
indices.each { |index| ThinkingSphinx::Deletion.perform index, instance }
|
15
8
|
end
|
16
9
|
|
17
10
|
private
|
@@ -20,10 +13,6 @@ class ThinkingSphinx::ActiveRecord::Callbacks::DeleteCallbacks <
|
|
20
13
|
ThinkingSphinx::Configuration.instance
|
21
14
|
end
|
22
15
|
|
23
|
-
def connection
|
24
|
-
@connection ||= ThinkingSphinx::Connection.new
|
25
|
-
end
|
26
|
-
|
27
16
|
def indices
|
28
17
|
config.preload_indices
|
29
18
|
config.indices_for_references instance.class.name.underscore.to_sym
|
@@ -1,55 +1,54 @@
|
|
1
1
|
module ThinkingSphinx::ActiveRecord::DatabaseAdapters
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
adapter = adapter_type_for(model)
|
6
|
-
klass = case adapter
|
7
|
-
when :mysql
|
8
|
-
ThinkingSphinx::ActiveRecord::DatabaseAdapters::MySQLAdapter
|
9
|
-
when :postgresql
|
10
|
-
ThinkingSphinx::ActiveRecord::DatabaseAdapters::PostgreSQLAdapter
|
11
|
-
else
|
12
|
-
raise "Invalid Database Adapter '#{adapter}': Thinking Sphinx only supports MySQL and PostgreSQL."
|
13
|
-
end
|
2
|
+
class << self
|
3
|
+
attr_accessor :default
|
14
4
|
|
15
|
-
|
16
|
-
|
5
|
+
def adapter_for(model)
|
6
|
+
return default.new(model) if default
|
7
|
+
|
8
|
+
adapter = adapter_type_for(model)
|
9
|
+
klass = case adapter
|
10
|
+
when :mysql
|
11
|
+
MySQLAdapter
|
12
|
+
when :postgresql
|
13
|
+
PostgreSQLAdapter
|
14
|
+
else
|
15
|
+
raise "Invalid Database Adapter '#{adapter}': Thinking Sphinx only supports MySQL and PostgreSQL."
|
16
|
+
end
|
17
|
+
|
18
|
+
klass.new model
|
19
|
+
end
|
17
20
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
:mysql
|
23
|
-
when "ActiveRecord::ConnectionAdapters::PostgreSQLAdapter"
|
24
|
-
:postgresql
|
25
|
-
when "ActiveRecord::ConnectionAdapters::JdbcAdapter"
|
26
|
-
case model.connection.config[:adapter]
|
27
|
-
when "jdbcmysql"
|
21
|
+
def adapter_type_for(model)
|
22
|
+
class_name = model.connection.class.name
|
23
|
+
case class_name.split('::').last
|
24
|
+
when 'MysqlAdapter', 'Mysql2Adapter'
|
28
25
|
:mysql
|
29
|
-
when
|
26
|
+
when 'PostgreSQLAdapter'
|
30
27
|
:postgresql
|
31
|
-
when
|
32
|
-
|
33
|
-
if match
|
34
|
-
match[:adapter].to_sym
|
35
|
-
else
|
36
|
-
model.connection.config[:adapter]
|
37
|
-
end
|
28
|
+
when 'JdbcAdapter'
|
29
|
+
adapter_type_for_jdbc(model)
|
38
30
|
else
|
39
|
-
|
31
|
+
class_name
|
40
32
|
end
|
41
|
-
else
|
42
|
-
model.connection.class.name
|
43
33
|
end
|
44
|
-
end
|
45
34
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
35
|
+
def adapter_type_for_jdbc(model)
|
36
|
+
case adapter = model.connection.config[:adapter]
|
37
|
+
when 'jdbcmysql'
|
38
|
+
:mysql
|
39
|
+
when 'jdbcpostgresql'
|
40
|
+
:postgresql
|
41
|
+
when 'jdbc'
|
42
|
+
adapter_type_for_jdbc_plain(adapter, model.connection.config[:url])
|
43
|
+
else adapter
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def adapter_type_for_jdbc_plain(adapter, url)
|
48
|
+
return adapter unless match = /^jdbc:(?<adapter>mysql|postgresql):\/\//.match(url)
|
50
49
|
|
51
|
-
|
52
|
-
|
50
|
+
match[:adapter].to_sym
|
51
|
+
end
|
53
52
|
end
|
54
53
|
end
|
55
54
|
|
@@ -14,11 +14,16 @@ class ThinkingSphinx::ActiveRecord::Polymorpher
|
|
14
14
|
|
15
15
|
def append_reflections
|
16
16
|
mappings.each do |class_name, name|
|
17
|
-
klass.reflections[name] ||=
|
18
|
-
FilteredReflection.clone_with_filter(reflection, name, class_name)
|
17
|
+
klass.reflections[name] ||= clone_with name, class_name
|
19
18
|
end
|
20
19
|
end
|
21
20
|
|
21
|
+
def clone_with(name, class_name)
|
22
|
+
ThinkingSphinx::ActiveRecord::FilteredReflection.clone_with_filter(
|
23
|
+
reflection, name, class_name
|
24
|
+
)
|
25
|
+
end
|
26
|
+
|
22
27
|
def mappings
|
23
28
|
@mappings ||= class_names.inject({}) do |hash, class_name|
|
24
29
|
hash[class_name] = "#{column.__name}_#{class_name.downcase}".to_sym
|
@@ -5,6 +5,13 @@ class ThinkingSphinx::ActiveRecord::PropertyQuery
|
|
5
5
|
|
6
6
|
def to_s
|
7
7
|
identifier = [type, property.name].compact.join(' ')
|
8
|
+
|
9
|
+
"#{identifier} from #{source_type}; #{queries.join('; ')}"
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
def queries
|
8
15
|
queries = []
|
9
16
|
if column.string?
|
10
17
|
queries << column.__name.strip.gsub(/\n/, "\\\n")
|
@@ -12,18 +19,20 @@ class ThinkingSphinx::ActiveRecord::PropertyQuery
|
|
12
19
|
queries << to_sql
|
13
20
|
queries << range_sql if ranged?
|
14
21
|
end
|
15
|
-
|
16
|
-
"#{identifier} from #{source_type}; #{queries.join('; ')}"
|
22
|
+
queries
|
17
23
|
end
|
18
24
|
|
19
|
-
private
|
20
|
-
|
21
25
|
attr_reader :property, :source, :type
|
22
26
|
|
23
27
|
def base_association
|
24
28
|
reflections.first
|
25
29
|
end
|
26
30
|
|
31
|
+
def base_association_class
|
32
|
+
base_association.klass
|
33
|
+
end
|
34
|
+
delegate :relation, :to => :base_association_class, :prefix => true
|
35
|
+
|
27
36
|
def column
|
28
37
|
@column ||= property.columns.first
|
29
38
|
end
|
@@ -40,7 +49,7 @@ class ThinkingSphinx::ActiveRecord::PropertyQuery
|
|
40
49
|
|
41
50
|
column.__stack.collect { |key|
|
42
51
|
reflection = base.reflections[key]
|
43
|
-
base
|
52
|
+
base = reflection.klass
|
44
53
|
|
45
54
|
extend_reflection reflection
|
46
55
|
}.flatten
|
@@ -64,12 +73,11 @@ class ThinkingSphinx::ActiveRecord::PropertyQuery
|
|
64
73
|
end
|
65
74
|
|
66
75
|
def quoted_foreign_key
|
67
|
-
quote_with_table base_association.
|
68
|
-
base_association.foreign_key
|
76
|
+
quote_with_table(base_association_class.table_name, base_association.foreign_key)
|
69
77
|
end
|
70
78
|
|
71
79
|
def quoted_primary_key
|
72
|
-
quote_with_table
|
80
|
+
quote_with_table(reflections.last.klass.table_name, column.__name)
|
73
81
|
end
|
74
82
|
|
75
83
|
def quote_with_table(table, column)
|
@@ -85,8 +93,9 @@ class ThinkingSphinx::ActiveRecord::PropertyQuery
|
|
85
93
|
end
|
86
94
|
|
87
95
|
def range_sql
|
88
|
-
|
89
|
-
|
96
|
+
base_association_class_relation.select(
|
97
|
+
"MIN(#{quoted_foreign_key}), MAX(#{quoted_foreign_key})"
|
98
|
+
).to_sql
|
90
99
|
end
|
91
100
|
|
92
101
|
def source_type
|
@@ -96,15 +105,10 @@ class ThinkingSphinx::ActiveRecord::PropertyQuery
|
|
96
105
|
def to_sql
|
97
106
|
raise "Could not determine SQL for MVA" if reflections.empty?
|
98
107
|
|
99
|
-
relation =
|
100
|
-
|
101
|
-
relation = relation.
|
102
|
-
|
103
|
-
if ranged?
|
104
|
-
relation = relation.where("#{quoted_foreign_key} >= $start")
|
105
|
-
relation = relation.where("#{quoted_foreign_key} <= $end")
|
106
|
-
end
|
107
|
-
|
108
|
+
relation = base_association_class_relation.select("#{quoted_foreign_key} #{offset} AS #{quote_column('id')}, #{quoted_primary_key} AS #{quote_column(property.name)}"
|
109
|
+
)
|
110
|
+
relation = relation.joins(joins) if joins.present?
|
111
|
+
relation = relation.where("#{quoted_foreign_key} BETWEEN $start AND $end") if ranged?
|
108
112
|
relation = relation.order("#{quoted_foreign_key} ASC") if type.nil?
|
109
113
|
|
110
114
|
relation.to_sql
|