ebeigarts-thinking-sphinx 1.1.22 → 1.2.10
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.textile +14 -0
- data/VERSION.yml +4 -0
- data/lib/thinking_sphinx.rb +60 -64
- data/lib/thinking_sphinx/active_record.rb +35 -7
- data/lib/thinking_sphinx/active_record/scopes.rb +39 -0
- data/lib/thinking_sphinx/adapters/postgresql_adapter.rb +3 -2
- data/lib/thinking_sphinx/attribute.rb +62 -22
- data/lib/thinking_sphinx/configuration.rb +21 -1
- data/lib/thinking_sphinx/core/array.rb +7 -0
- data/lib/thinking_sphinx/deltas/delayed_delta.rb +3 -0
- data/lib/thinking_sphinx/deploy/capistrano.rb +26 -8
- data/lib/thinking_sphinx/excerpter.rb +22 -0
- data/lib/thinking_sphinx/facet.rb +8 -2
- data/lib/thinking_sphinx/facet_search.rb +134 -0
- data/lib/thinking_sphinx/index.rb +2 -2
- data/lib/thinking_sphinx/index/builder.rb +0 -1
- data/lib/thinking_sphinx/property.rb +2 -0
- data/lib/thinking_sphinx/rails_additions.rb +14 -0
- data/lib/thinking_sphinx/search.rb +633 -671
- data/lib/thinking_sphinx/search_methods.rb +421 -0
- data/lib/thinking_sphinx/source.rb +5 -5
- data/lib/thinking_sphinx/source/internal_properties.rb +1 -1
- data/lib/thinking_sphinx/source/sql.rb +10 -8
- data/lib/thinking_sphinx/tasks.rb +14 -9
- data/spec/{unit → lib}/thinking_sphinx/active_record/delta_spec.rb +1 -1
- data/spec/{unit → lib}/thinking_sphinx/active_record/has_many_association_spec.rb +0 -0
- data/spec/lib/thinking_sphinx/active_record/scopes_spec.rb +96 -0
- data/spec/{unit → lib}/thinking_sphinx/active_record_spec.rb +44 -5
- data/spec/{unit → lib}/thinking_sphinx/association_spec.rb +0 -0
- data/spec/{unit → lib}/thinking_sphinx/attribute_spec.rb +110 -3
- data/spec/{unit → lib}/thinking_sphinx/configuration_spec.rb +87 -41
- data/spec/lib/thinking_sphinx/core/array_spec.rb +9 -0
- data/spec/{unit → lib}/thinking_sphinx/core/string_spec.rb +0 -0
- data/spec/lib/thinking_sphinx/excerpter_spec.rb +49 -0
- data/spec/lib/thinking_sphinx/facet_search_spec.rb +176 -0
- data/spec/{unit → lib}/thinking_sphinx/facet_spec.rb +34 -15
- data/spec/{unit → lib}/thinking_sphinx/field_spec.rb +0 -0
- data/spec/{unit → lib}/thinking_sphinx/index/builder_spec.rb +100 -0
- data/spec/{unit → lib}/thinking_sphinx/index/faux_column_spec.rb +0 -0
- data/spec/{unit → lib}/thinking_sphinx/index_spec.rb +0 -0
- data/spec/{unit → lib}/thinking_sphinx/rails_additions_spec.rb +12 -0
- data/spec/lib/thinking_sphinx/search_methods_spec.rb +152 -0
- data/spec/lib/thinking_sphinx/search_spec.rb +1066 -0
- data/spec/{unit → lib}/thinking_sphinx/source_spec.rb +10 -0
- data/spec/{unit → lib}/thinking_sphinx_spec.rb +10 -0
- data/tasks/distribution.rb +20 -38
- data/tasks/testing.rb +3 -1
- data/vendor/riddle/lib/riddle.rb +1 -1
- data/vendor/riddle/lib/riddle/client.rb +3 -0
- data/vendor/riddle/lib/riddle/client/message.rb +4 -3
- data/vendor/riddle/lib/riddle/configuration/section.rb +1 -1
- data/vendor/riddle/lib/riddle/controller.rb +17 -7
- metadata +63 -83
- data/lib/thinking_sphinx/active_record/search.rb +0 -57
- data/lib/thinking_sphinx/collection.rb +0 -148
- data/lib/thinking_sphinx/facet_collection.rb +0 -59
- data/lib/thinking_sphinx/search/facets.rb +0 -104
- data/spec/unit/thinking_sphinx/active_record/search_spec.rb +0 -107
- data/spec/unit/thinking_sphinx/collection_spec.rb +0 -15
- data/spec/unit/thinking_sphinx/facet_collection_spec.rb +0 -64
- data/spec/unit/thinking_sphinx/search_spec.rb +0 -228
|
@@ -2,7 +2,7 @@ module ThinkingSphinx
|
|
|
2
2
|
class Source
|
|
3
3
|
module InternalProperties
|
|
4
4
|
def add_internal_attributes_and_facets
|
|
5
|
-
add_internal_attribute :sphinx_internal_id, :integer, @model.
|
|
5
|
+
add_internal_attribute :sphinx_internal_id, :integer, @model.primary_key_for_sphinx.to_sym
|
|
6
6
|
add_internal_attribute :class_crc, :integer, crc_column, true
|
|
7
7
|
add_internal_attribute :subclass_crcs, :multi, subclasses_to_s
|
|
8
8
|
add_internal_attribute :sphinx_deleted, :integer, "0"
|
|
@@ -33,10 +33,10 @@ GROUP BY #{ sql_group_clause }
|
|
|
33
33
|
return nil if @index.options[:disable_range]
|
|
34
34
|
|
|
35
35
|
min_statement = adapter.convert_nulls(
|
|
36
|
-
"MIN(#{quote_column(@model.
|
|
36
|
+
"MIN(#{quote_column(@model.primary_key_for_sphinx)})", 1
|
|
37
37
|
)
|
|
38
38
|
max_statement = adapter.convert_nulls(
|
|
39
|
-
"MAX(#{quote_column(@model.
|
|
39
|
+
"MAX(#{quote_column(@model.primary_key_for_sphinx)})", 1
|
|
40
40
|
)
|
|
41
41
|
|
|
42
42
|
sql = "SELECT #{min_statement}, #{max_statement} " +
|
|
@@ -53,14 +53,14 @@ GROUP BY #{ sql_group_clause }
|
|
|
53
53
|
#
|
|
54
54
|
def to_sql_query_info(offset)
|
|
55
55
|
"SELECT * FROM #{@model.quoted_table_name} WHERE " +
|
|
56
|
-
"#{quote_column(@model.
|
|
56
|
+
"#{quote_column(@model.primary_key_for_sphinx)} = (($id - #{offset}) / #{ThinkingSphinx.indexed_models.size})"
|
|
57
57
|
end
|
|
58
58
|
|
|
59
59
|
def sql_select_clause(offset)
|
|
60
60
|
unique_id_expr = ThinkingSphinx.unique_id_expression(offset)
|
|
61
61
|
|
|
62
62
|
(
|
|
63
|
-
["#{@model.quoted_table_name}.#{quote_column(@model.
|
|
63
|
+
["#{@model.quoted_table_name}.#{quote_column(@model.primary_key_for_sphinx)} #{unique_id_expr} AS #{quote_column(@model.primary_key_for_sphinx)} "] +
|
|
64
64
|
@fields.collect { |field| field.to_select_sql } +
|
|
65
65
|
@attributes.collect { |attribute| attribute.to_select_sql }
|
|
66
66
|
).compact.join(", ")
|
|
@@ -69,8 +69,8 @@ GROUP BY #{ sql_group_clause }
|
|
|
69
69
|
def sql_where_clause(options)
|
|
70
70
|
logic = []
|
|
71
71
|
logic += [
|
|
72
|
-
"#{@model.quoted_table_name}.#{quote_column(@model.
|
|
73
|
-
"#{@model.quoted_table_name}.#{quote_column(@model.
|
|
72
|
+
"#{@model.quoted_table_name}.#{quote_column(@model.primary_key_for_sphinx)} >= $start",
|
|
73
|
+
"#{@model.quoted_table_name}.#{quote_column(@model.primary_key_for_sphinx)} <= $end"
|
|
74
74
|
] unless @index.options[:disable_range]
|
|
75
75
|
|
|
76
76
|
if self.delta? && !@index.delta_object.clause(@model, options[:delta]).blank?
|
|
@@ -88,7 +88,7 @@ GROUP BY #{ sql_group_clause }
|
|
|
88
88
|
end
|
|
89
89
|
|
|
90
90
|
(
|
|
91
|
-
["#{@model.quoted_table_name}.#{quote_column(@model.
|
|
91
|
+
["#{@model.quoted_table_name}.#{quote_column(@model.primary_key_for_sphinx)}"] +
|
|
92
92
|
@fields.collect { |field| field.to_group_sql }.compact +
|
|
93
93
|
@attributes.collect { |attribute| attribute.to_group_sql }.compact +
|
|
94
94
|
@groupings + internal_groupings
|
|
@@ -112,7 +112,9 @@ GROUP BY #{ sql_group_clause }
|
|
|
112
112
|
end
|
|
113
113
|
|
|
114
114
|
def crc_column
|
|
115
|
-
if @model.
|
|
115
|
+
if @model.table_exists? &&
|
|
116
|
+
@model.column_names.include?(@model.inheritance_column)
|
|
117
|
+
|
|
116
118
|
adapter.cast_to_unsigned(adapter.convert_nulls(
|
|
117
119
|
adapter.crc(adapter.quote_with_table(@model.inheritance_column), true),
|
|
118
120
|
@model.to_crc32
|
|
@@ -12,7 +12,7 @@ namespace :thinking_sphinx do
|
|
|
12
12
|
|
|
13
13
|
desc "Output the current Thinking Sphinx version"
|
|
14
14
|
task :version => :app_env do
|
|
15
|
-
puts "Thinking Sphinx v" + ThinkingSphinx
|
|
15
|
+
puts "Thinking Sphinx v" + ThinkingSphinx.version
|
|
16
16
|
end
|
|
17
17
|
|
|
18
18
|
desc "Stop if running, then start a Sphinx searchd daemon using Thinking Sphinx's settings"
|
|
@@ -30,7 +30,7 @@ namespace :thinking_sphinx do
|
|
|
30
30
|
|
|
31
31
|
Dir["#{config.searchd_file_path}/*.spl"].each { |file| File.delete(file) }
|
|
32
32
|
|
|
33
|
-
system! "#{config.bin_path}#{config.searchd_binary_name} --pidfile --config #{config.config_file}"
|
|
33
|
+
system! "#{config.bin_path}#{config.searchd_binary_name} --pidfile --config \"#{config.config_file}\""
|
|
34
34
|
|
|
35
35
|
sleep(2)
|
|
36
36
|
|
|
@@ -43,11 +43,14 @@ namespace :thinking_sphinx do
|
|
|
43
43
|
|
|
44
44
|
desc "Stop Sphinx using Thinking Sphinx's settings"
|
|
45
45
|
task :stop => :app_env do
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
46
|
+
unless sphinx_running?
|
|
47
|
+
puts "searchd is not running"
|
|
48
|
+
else
|
|
49
|
+
config = ThinkingSphinx::Configuration.instance
|
|
50
|
+
pid = sphinx_pid
|
|
51
|
+
system! "#{config.bin_path}#{config.searchd_binary_name} --stop --config \"#{config.config_file}\""
|
|
52
|
+
puts "Stopped search daemon (pid #{pid})."
|
|
53
|
+
end
|
|
51
54
|
end
|
|
52
55
|
|
|
53
56
|
desc "Restart Sphinx"
|
|
@@ -71,7 +74,7 @@ namespace :thinking_sphinx do
|
|
|
71
74
|
end
|
|
72
75
|
|
|
73
76
|
FileUtils.mkdir_p config.searchd_file_path
|
|
74
|
-
cmd = "#{config.bin_path}#{config.indexer_binary_name} --config #{config.config_file} --all"
|
|
77
|
+
cmd = "#{config.bin_path}#{config.indexer_binary_name} --config \"#{config.config_file}\" --all"
|
|
75
78
|
cmd << " --rotate" if sphinx_running?
|
|
76
79
|
|
|
77
80
|
system! cmd
|
|
@@ -111,6 +114,7 @@ namespace :thinking_sphinx do
|
|
|
111
114
|
# http://www.sphinxsearch.com/docs/current.html#xmlpipe2
|
|
112
115
|
desc "Streams XML data to STDOUT"
|
|
113
116
|
task :xml => :app_env do
|
|
117
|
+
ThinkingSphinx::Configuration.instance.load_models
|
|
114
118
|
source_name = ENV["NAME"]
|
|
115
119
|
# STDERR.puts "Source name: #{source_name}"
|
|
116
120
|
source_name =~ /^(.+)_(delta|core)_(\d+)$/
|
|
@@ -141,7 +145,8 @@ namespace :thinking_sphinx do
|
|
|
141
145
|
# STDERR.puts "fetching #{start_id}.. "
|
|
142
146
|
# STDERR.puts query
|
|
143
147
|
model_klass.sphinx_database_adapter.select_each(query) do |values|
|
|
144
|
-
|
|
148
|
+
pk_name = model_klass.primary_key_for_sphinx.to_s
|
|
149
|
+
id = values.delete(pk_name)
|
|
145
150
|
puts %{<sphinx:document id="#{id.to_i}">}
|
|
146
151
|
values.each do |k, v|
|
|
147
152
|
if source.sql_attr_bool.include?(k.to_sym)
|
|
File without changes
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
require 'spec/spec_helper'
|
|
2
|
+
|
|
3
|
+
describe ThinkingSphinx::ActiveRecord::Scopes do
|
|
4
|
+
after :each do
|
|
5
|
+
Alpha.remove_sphinx_scopes
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
it "should be included into models with indexes" do
|
|
9
|
+
Alpha.included_modules.should include(ThinkingSphinx::ActiveRecord::Scopes)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
it "should not be included into models without indexes" do
|
|
13
|
+
Gamma.included_modules.should_not include(
|
|
14
|
+
ThinkingSphinx::ActiveRecord::Scopes
|
|
15
|
+
)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
describe '.sphinx_scope' do
|
|
19
|
+
before :each do
|
|
20
|
+
Alpha.sphinx_scope(:by_name) { |name| {:conditions => {:name => name}} }
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
it "should define a method on the model" do
|
|
24
|
+
Alpha.should respond_to(:by_name)
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
describe '.sphinx_scopes' do
|
|
29
|
+
before :each do
|
|
30
|
+
Alpha.sphinx_scope(:by_name) { |name| {:conditions => {:name => name}} }
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
it "should return an array of defined scope names as symbols" do
|
|
34
|
+
Alpha.sphinx_scopes.should == [:by_name]
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
describe '.remove_sphinx_scopes' do
|
|
39
|
+
before :each do
|
|
40
|
+
Alpha.sphinx_scope(:by_name) { |name| {:conditions => {:name => name}} }
|
|
41
|
+
Alpha.remove_sphinx_scopes
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
it "should remove sphinx scope methods" do
|
|
45
|
+
Alpha.should_not respond_to(:by_name)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
it "should empty the list of sphinx scopes" do
|
|
49
|
+
Alpha.sphinx_scopes.should be_empty
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
describe '.example_scope' do
|
|
54
|
+
before :each do
|
|
55
|
+
Alpha.sphinx_scope(:by_name) { |name| {:conditions => {:name => name}} }
|
|
56
|
+
Alpha.sphinx_scope(:by_foo) { |foo| {:conditions => {:foo => foo}} }
|
|
57
|
+
Alpha.sphinx_scope(:with_betas) { {:classes => [Beta]} }
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
it "should return a ThinkingSphinx::Search object" do
|
|
61
|
+
Alpha.by_name('foo').should be_a(ThinkingSphinx::Search)
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
it "should set the classes option" do
|
|
65
|
+
Alpha.by_name('foo').options[:classes].should == [Alpha]
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
it "should be able to be called on a ThinkingSphinx::Search object" do
|
|
69
|
+
search = ThinkingSphinx::Search.new(:classes => [Alpha])
|
|
70
|
+
lambda {
|
|
71
|
+
search.by_name('foo')
|
|
72
|
+
}.should_not raise_error
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
it "should return the search object it gets called upon" do
|
|
76
|
+
search = ThinkingSphinx::Search.new(:classes => [Alpha])
|
|
77
|
+
search.by_name('foo').should == search
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
it "should apply the scope options to the underlying search object" do
|
|
81
|
+
search = ThinkingSphinx::Search.new(:classes => [Alpha])
|
|
82
|
+
search.by_name('foo').options[:conditions].should == {:name => 'foo'}
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
it "should combine hash option scopes such as :conditions" do
|
|
86
|
+
search = ThinkingSphinx::Search.new(:classes => [Alpha])
|
|
87
|
+
search.by_name('foo').by_foo('bar').options[:conditions].
|
|
88
|
+
should == {:name => 'foo', :foo => 'bar'}
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
it "should combine array option scopes such as :classes" do
|
|
92
|
+
search = ThinkingSphinx::Search.new(:classes => [Alpha])
|
|
93
|
+
search.with_betas.options[:classes].should == [Alpha, Beta]
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
end
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
require 'spec/spec_helper'
|
|
2
2
|
|
|
3
|
-
describe
|
|
4
|
-
describe
|
|
3
|
+
describe ThinkingSphinx::ActiveRecord do
|
|
4
|
+
describe '.define_index' do
|
|
5
5
|
before :each do
|
|
6
6
|
module ::TestModule
|
|
7
7
|
class TestModel < ActiveRecord::Base; end
|
|
@@ -154,7 +154,7 @@ describe "ThinkingSphinx::ActiveRecord" do
|
|
|
154
154
|
end
|
|
155
155
|
end
|
|
156
156
|
|
|
157
|
-
describe
|
|
157
|
+
describe '.source_of_sphinx_index' do
|
|
158
158
|
it "should return self if model defines an index" do
|
|
159
159
|
Person.source_of_sphinx_index.should == Person
|
|
160
160
|
end
|
|
@@ -164,13 +164,13 @@ describe "ThinkingSphinx::ActiveRecord" do
|
|
|
164
164
|
end
|
|
165
165
|
end
|
|
166
166
|
|
|
167
|
-
describe
|
|
167
|
+
describe '.to_crc32' do
|
|
168
168
|
it "should return an integer" do
|
|
169
169
|
Person.to_crc32.should be_a_kind_of(Integer)
|
|
170
170
|
end
|
|
171
171
|
end
|
|
172
172
|
|
|
173
|
-
describe
|
|
173
|
+
describe '.to_crc32s' do
|
|
174
174
|
it "should return an array" do
|
|
175
175
|
Person.to_crc32s.should be_a_kind_of(Array)
|
|
176
176
|
end
|
|
@@ -326,4 +326,43 @@ describe "ThinkingSphinx::ActiveRecord" do
|
|
|
326
326
|
|
|
327
327
|
(beta.id * model_count + offset).should == beta.sphinx_document_id
|
|
328
328
|
end
|
|
329
|
+
|
|
330
|
+
describe '#primary_key_for_sphinx' do
|
|
331
|
+
before :each do
|
|
332
|
+
@person = Person.find(:first)
|
|
333
|
+
end
|
|
334
|
+
|
|
335
|
+
after :each do
|
|
336
|
+
Person.set_sphinx_primary_key nil
|
|
337
|
+
end
|
|
338
|
+
|
|
339
|
+
it "should return the id by default" do
|
|
340
|
+
@person.primary_key_for_sphinx.should == @person.id
|
|
341
|
+
end
|
|
342
|
+
|
|
343
|
+
it "should use the sphinx primary key to determine the value" do
|
|
344
|
+
Person.set_sphinx_primary_key :first_name
|
|
345
|
+
@person.primary_key_for_sphinx.should == @person.first_name
|
|
346
|
+
end
|
|
347
|
+
|
|
348
|
+
it "should not use accessor methods but the attributes hash" do
|
|
349
|
+
id = @person.id
|
|
350
|
+
@person.stub!(:id => 'unique_hash')
|
|
351
|
+
@person.primary_key_for_sphinx.should == id
|
|
352
|
+
end
|
|
353
|
+
end
|
|
354
|
+
|
|
355
|
+
describe '.sphinx_index_names' do
|
|
356
|
+
it "should return the core index" do
|
|
357
|
+
Alpha.sphinx_index_names.should == ['alpha_core']
|
|
358
|
+
end
|
|
359
|
+
|
|
360
|
+
it "should return the delta index if enabled" do
|
|
361
|
+
Beta.sphinx_index_names.should == ['beta_core', 'beta_delta']
|
|
362
|
+
end
|
|
363
|
+
|
|
364
|
+
it "should return the superclass with an index definition" do
|
|
365
|
+
Parent.sphinx_index_names.should == ['person_core', 'person_delta']
|
|
366
|
+
end
|
|
367
|
+
end
|
|
329
368
|
end
|
|
File without changes
|
|
@@ -4,6 +4,8 @@ describe ThinkingSphinx::Attribute do
|
|
|
4
4
|
before :each do
|
|
5
5
|
@index = ThinkingSphinx::Index.new(Person)
|
|
6
6
|
@source = ThinkingSphinx::Source.new(@index)
|
|
7
|
+
|
|
8
|
+
@index.delta_object = ThinkingSphinx::Deltas::DefaultDelta.new @index, @index.local_options
|
|
7
9
|
end
|
|
8
10
|
|
|
9
11
|
describe '#initialize' do
|
|
@@ -86,6 +88,19 @@ describe ThinkingSphinx::Attribute do
|
|
|
86
88
|
end
|
|
87
89
|
end
|
|
88
90
|
|
|
91
|
+
describe '#to_select_sql' do
|
|
92
|
+
it "should convert a mixture of dates and datetimes to timestamps" do
|
|
93
|
+
attribute = ThinkingSphinx::Attribute.new(@source,
|
|
94
|
+
[ ThinkingSphinx::Index::FauxColumn.new(:created_at),
|
|
95
|
+
ThinkingSphinx::Index::FauxColumn.new(:created_on) ],
|
|
96
|
+
:as => :times
|
|
97
|
+
)
|
|
98
|
+
attribute.model = Friendship
|
|
99
|
+
|
|
100
|
+
attribute.to_select_sql.should == "CONCAT_WS(',', UNIX_TIMESTAMP(`friendships`.`created_at`), UNIX_TIMESTAMP(`friendships`.`created_on`)) AS `times`"
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
|
|
89
104
|
describe "is_many? method" do
|
|
90
105
|
before :each do
|
|
91
106
|
@assoc_a = Object.stub_instance(:is_many? => true)
|
|
@@ -189,7 +204,7 @@ describe ThinkingSphinx::Attribute do
|
|
|
189
204
|
attribute.model = Person
|
|
190
205
|
attribute.columns.each { |col| attribute.associations[col] = [] }
|
|
191
206
|
|
|
192
|
-
attribute.
|
|
207
|
+
attribute.should be_all_ints
|
|
193
208
|
end
|
|
194
209
|
|
|
195
210
|
it "should return false if only some columns are integers" do
|
|
@@ -200,7 +215,7 @@ describe ThinkingSphinx::Attribute do
|
|
|
200
215
|
attribute.model = Person
|
|
201
216
|
attribute.columns.each { |col| attribute.associations[col] = [] }
|
|
202
217
|
|
|
203
|
-
attribute.
|
|
218
|
+
attribute.should_not be_all_ints
|
|
204
219
|
end
|
|
205
220
|
|
|
206
221
|
it "should return false if no columns are integers" do
|
|
@@ -211,7 +226,42 @@ describe ThinkingSphinx::Attribute do
|
|
|
211
226
|
attribute.model = Person
|
|
212
227
|
attribute.columns.each { |col| attribute.associations[col] = [] }
|
|
213
228
|
|
|
214
|
-
attribute.
|
|
229
|
+
attribute.should_not be_all_ints
|
|
230
|
+
end
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
describe "all_datetimes? method" do
|
|
234
|
+
it "should return true if all columns are datetimes" do
|
|
235
|
+
attribute = ThinkingSphinx::Attribute.new(@source,
|
|
236
|
+
[ ThinkingSphinx::Index::FauxColumn.new(:created_at),
|
|
237
|
+
ThinkingSphinx::Index::FauxColumn.new(:updated_at) ]
|
|
238
|
+
)
|
|
239
|
+
attribute.model = Friendship
|
|
240
|
+
attribute.columns.each { |col| attribute.associations[col] = [] }
|
|
241
|
+
|
|
242
|
+
attribute.should be_all_datetimes
|
|
243
|
+
end
|
|
244
|
+
|
|
245
|
+
it "should return false if only some columns are datetimes" do
|
|
246
|
+
attribute = ThinkingSphinx::Attribute.new(@source,
|
|
247
|
+
[ ThinkingSphinx::Index::FauxColumn.new(:id),
|
|
248
|
+
ThinkingSphinx::Index::FauxColumn.new(:created_at) ]
|
|
249
|
+
)
|
|
250
|
+
attribute.model = Friendship
|
|
251
|
+
attribute.columns.each { |col| attribute.associations[col] = [] }
|
|
252
|
+
|
|
253
|
+
attribute.should_not be_all_datetimes
|
|
254
|
+
end
|
|
255
|
+
|
|
256
|
+
it "should return true if all columns can be " do
|
|
257
|
+
attribute = ThinkingSphinx::Attribute.new(@source,
|
|
258
|
+
[ ThinkingSphinx::Index::FauxColumn.new(:created_at),
|
|
259
|
+
ThinkingSphinx::Index::FauxColumn.new(:created_on) ]
|
|
260
|
+
)
|
|
261
|
+
attribute.model = Friendship
|
|
262
|
+
attribute.columns.each { |col| attribute.associations[col] = [] }
|
|
263
|
+
|
|
264
|
+
attribute.should be_all_datetimes
|
|
215
265
|
end
|
|
216
266
|
end
|
|
217
267
|
|
|
@@ -232,6 +282,23 @@ describe ThinkingSphinx::Attribute do
|
|
|
232
282
|
end
|
|
233
283
|
end
|
|
234
284
|
|
|
285
|
+
describe "MVA with source query for a delta source" do
|
|
286
|
+
before :each do
|
|
287
|
+
@attribute = ThinkingSphinx::Attribute.new(@source,
|
|
288
|
+
[ThinkingSphinx::Index::FauxColumn.new(:tags, :id)],
|
|
289
|
+
:as => :tag_ids, :source => :query
|
|
290
|
+
)
|
|
291
|
+
end
|
|
292
|
+
|
|
293
|
+
it "should use a query" do
|
|
294
|
+
@attribute.type_to_config.should == :sql_attr_multi
|
|
295
|
+
|
|
296
|
+
declaration, query = @attribute.config_value(nil, true).split('; ')
|
|
297
|
+
declaration.should == "uint tag_ids from query"
|
|
298
|
+
query.should == "SELECT `tags`.`person_id` #{ThinkingSphinx.unique_id_expression} AS `id`, `tags`.`id` AS `tag_ids` FROM `tags` WHERE `tags`.`person_id` IN (SELECT `id` FROM `people` WHERE `people`.`delta` = 1)"
|
|
299
|
+
end
|
|
300
|
+
end
|
|
301
|
+
|
|
235
302
|
describe "MVA via a HABTM association with a source query" do
|
|
236
303
|
before :each do
|
|
237
304
|
@attribute = ThinkingSphinx::Attribute.new(@source,
|
|
@@ -267,6 +334,24 @@ describe ThinkingSphinx::Attribute do
|
|
|
267
334
|
end
|
|
268
335
|
end
|
|
269
336
|
|
|
337
|
+
describe "MVA with ranged source query for a delta source" do
|
|
338
|
+
before :each do
|
|
339
|
+
@attribute = ThinkingSphinx::Attribute.new(@source,
|
|
340
|
+
[ThinkingSphinx::Index::FauxColumn.new(:tags, :id)],
|
|
341
|
+
:as => :tag_ids, :source => :ranged_query
|
|
342
|
+
)
|
|
343
|
+
end
|
|
344
|
+
|
|
345
|
+
it "should use a ranged query" do
|
|
346
|
+
@attribute.type_to_config.should == :sql_attr_multi
|
|
347
|
+
|
|
348
|
+
declaration, query, range_query = @attribute.config_value(nil, true).split('; ')
|
|
349
|
+
declaration.should == "uint tag_ids from ranged-query"
|
|
350
|
+
query.should == "SELECT `tags`.`person_id` #{ThinkingSphinx.unique_id_expression} AS `id`, `tags`.`id` AS `tag_ids` FROM `tags` WHERE `tags`.`person_id` >= $start AND `tags`.`person_id` <= $end AND `tags`.`person_id` IN (SELECT `id` FROM `people` WHERE `people`.`delta` = 1)"
|
|
351
|
+
range_query.should == "SELECT MIN(`tags`.`person_id`), MAX(`tags`.`person_id`) FROM `tags`"
|
|
352
|
+
end
|
|
353
|
+
end
|
|
354
|
+
|
|
270
355
|
describe "MVA via a has-many :through with a ranged source query" do
|
|
271
356
|
before :each do
|
|
272
357
|
@attribute = ThinkingSphinx::Attribute.new(@source,
|
|
@@ -341,6 +426,28 @@ describe ThinkingSphinx::Attribute do
|
|
|
341
426
|
end
|
|
342
427
|
end
|
|
343
428
|
|
|
429
|
+
describe "MVA via two has-many associations with a ranged source query for a delta source" do
|
|
430
|
+
before :each do
|
|
431
|
+
@index = ThinkingSphinx::Index.new(Alpha)
|
|
432
|
+
@source = ThinkingSphinx::Source.new(@index)
|
|
433
|
+
@attribute = ThinkingSphinx::Attribute.new(@source,
|
|
434
|
+
[ThinkingSphinx::Index::FauxColumn.new(:betas, :gammas, :value)],
|
|
435
|
+
:as => :gamma_values, :source => :ranged_query
|
|
436
|
+
)
|
|
437
|
+
|
|
438
|
+
@index.delta_object = ThinkingSphinx::Deltas::DefaultDelta.new @index, @index.local_options
|
|
439
|
+
end
|
|
440
|
+
|
|
441
|
+
it "should use a ranged query" do
|
|
442
|
+
@attribute.type_to_config.should == :sql_attr_multi
|
|
443
|
+
|
|
444
|
+
declaration, query, range_query = @attribute.config_value(nil, true).split('; ')
|
|
445
|
+
declaration.should == "uint gamma_values from ranged-query"
|
|
446
|
+
query.should == "SELECT `betas`.`alpha_id` #{ThinkingSphinx.unique_id_expression} AS `id`, `gammas`.`value` AS `gamma_values` FROM `betas` LEFT OUTER JOIN `gammas` ON gammas.beta_id = betas.id WHERE `betas`.`alpha_id` >= $start AND `betas`.`alpha_id` <= $end AND `betas`.`alpha_id` IN (SELECT `id` FROM `alphas` WHERE `alphas`.`delta` = 1)"
|
|
447
|
+
range_query.should == "SELECT MIN(`betas`.`alpha_id`), MAX(`betas`.`alpha_id`) FROM `betas`"
|
|
448
|
+
end
|
|
449
|
+
end
|
|
450
|
+
|
|
344
451
|
describe "with custom queries" do
|
|
345
452
|
before :each do
|
|
346
453
|
index = CricketTeam.sphinx_indexes.first
|