thinking-sphinx 3.2.0 → 3.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +6 -2
- data/Appraisals +13 -0
- data/Gemfile +2 -1
- data/HISTORY +19 -0
- data/README.textile +3 -2
- data/gemfiles/rails_3_2.gemfile +2 -1
- data/gemfiles/rails_4_0.gemfile +2 -1
- data/gemfiles/rails_4_1.gemfile +2 -1
- data/gemfiles/rails_4_2.gemfile +2 -1
- data/gemfiles/rails_5_0.gemfile +12 -0
- data/lib/thinking_sphinx.rb +2 -0
- data/lib/thinking_sphinx/active_record/attribute/type.rb +17 -3
- data/lib/thinking_sphinx/active_record/callbacks/delta_callbacks.rb +12 -4
- data/lib/thinking_sphinx/active_record/database_adapters.rb +1 -1
- data/lib/thinking_sphinx/active_record/sql_builder/query.rb +4 -0
- data/lib/thinking_sphinx/active_record/sql_source.rb +1 -1
- data/lib/thinking_sphinx/configuration.rb +3 -2
- data/lib/thinking_sphinx/connection.rb +23 -10
- data/lib/thinking_sphinx/deltas/index_job.rb +6 -2
- data/lib/thinking_sphinx/errors.rb +25 -0
- data/lib/thinking_sphinx/middlewares/active_record_translator.rb +14 -2
- data/lib/thinking_sphinx/railtie.rb +1 -1
- data/lib/thinking_sphinx/rake_interface.rb +71 -23
- data/lib/thinking_sphinx/real_time/callbacks/real_time_callbacks.rb +15 -7
- data/lib/thinking_sphinx/real_time/populator.rb +3 -3
- data/lib/thinking_sphinx/tasks.rb +7 -8
- data/lib/thinking_sphinx/wildcard.rb +1 -1
- data/spec/acceptance/association_scoping_spec.rb +5 -5
- data/spec/acceptance/attribute_access_spec.rb +4 -4
- data/spec/acceptance/attribute_updates_spec.rb +3 -3
- data/spec/acceptance/batch_searching_spec.rb +4 -4
- data/spec/acceptance/big_integers_spec.rb +6 -6
- data/spec/acceptance/connection_spec.rb +23 -0
- data/spec/acceptance/excerpts_spec.rb +8 -8
- data/spec/acceptance/facets_spec.rb +13 -13
- data/spec/acceptance/geosearching_spec.rb +8 -8
- data/spec/acceptance/grouping_by_attributes_spec.rb +10 -10
- data/spec/acceptance/index_options_spec.rb +16 -16
- data/spec/acceptance/indexing_spec.rb +3 -3
- data/spec/acceptance/paginating_search_results_spec.rb +3 -3
- data/spec/acceptance/real_time_updates_spec.rb +4 -4
- data/spec/acceptance/remove_deleted_records_spec.rb +12 -12
- data/spec/acceptance/search_counts_spec.rb +2 -2
- data/spec/acceptance/search_for_just_ids_spec.rb +2 -2
- data/spec/acceptance/searching_across_models_spec.rb +6 -6
- data/spec/acceptance/searching_across_schemas_spec.rb +10 -10
- data/spec/acceptance/searching_on_fields_spec.rb +9 -9
- data/spec/acceptance/searching_with_filters_spec.rb +16 -16
- data/spec/acceptance/searching_with_sti_spec.rb +9 -9
- data/spec/acceptance/searching_within_a_model_spec.rb +17 -17
- data/spec/acceptance/sorting_search_results_spec.rb +6 -6
- data/spec/acceptance/specifying_sql_spec.rb +62 -62
- data/spec/acceptance/sphinx_scopes_spec.rb +9 -9
- data/spec/acceptance/sql_deltas_spec.rb +7 -7
- data/spec/acceptance/support/database_cleaner.rb +1 -1
- data/spec/acceptance/support/sphinx_controller.rb +4 -1
- data/spec/acceptance/support/sphinx_helpers.rb +4 -0
- data/spec/acceptance/suspended_deltas_spec.rb +9 -9
- data/spec/internal/app/indices/article_index.rb +2 -2
- data/spec/internal/app/indices/book_index.rb +2 -1
- data/spec/internal/app/indices/product_index.rb +0 -2
- data/spec/internal/app/models/categorisation.rb +8 -1
- data/spec/spec_helper.rb +2 -0
- data/spec/support/json_column.rb +5 -1
- data/spec/support/multi_schema.rb +3 -1
- data/spec/support/sphinx_yaml_helpers.rb +1 -1
- data/spec/thinking_sphinx/active_record/association_spec.rb +1 -1
- data/spec/thinking_sphinx/active_record/attribute/type_spec.rb +41 -38
- data/spec/thinking_sphinx/active_record/base_spec.rb +29 -29
- data/spec/thinking_sphinx/active_record/callbacks/delete_callbacks_spec.rb +10 -10
- data/spec/thinking_sphinx/active_record/callbacks/delta_callbacks_spec.rb +48 -25
- data/spec/thinking_sphinx/active_record/callbacks/update_callbacks_spec.rb +8 -8
- data/spec/thinking_sphinx/active_record/column_spec.rb +13 -13
- data/spec/thinking_sphinx/active_record/column_sql_presenter_spec.rb +5 -5
- data/spec/thinking_sphinx/active_record/database_adapters/abstract_adapter_spec.rb +5 -5
- data/spec/thinking_sphinx/active_record/database_adapters/mysql_adapter_spec.rb +11 -11
- data/spec/thinking_sphinx/active_record/database_adapters/postgresql_adapter_spec.rb +13 -13
- data/spec/thinking_sphinx/active_record/database_adapters_spec.rb +48 -48
- data/spec/thinking_sphinx/active_record/field_spec.rb +7 -7
- data/spec/thinking_sphinx/active_record/filter_reflection_spec.rb +32 -32
- data/spec/thinking_sphinx/active_record/index_spec.rb +35 -36
- data/spec/thinking_sphinx/active_record/interpreter_spec.rb +51 -51
- data/spec/thinking_sphinx/active_record/polymorpher_spec.rb +14 -14
- data/spec/thinking_sphinx/active_record/property_sql_presenter_spec.rb +67 -67
- data/spec/thinking_sphinx/active_record/sql_builder_spec.rb +140 -140
- data/spec/thinking_sphinx/active_record/sql_source_spec.rb +97 -95
- data/spec/thinking_sphinx/configuration_spec.rb +81 -81
- data/spec/thinking_sphinx/connection_spec.rb +13 -13
- data/spec/thinking_sphinx/deletion_spec.rb +11 -11
- data/spec/thinking_sphinx/deltas/default_delta_spec.rb +20 -20
- data/spec/thinking_sphinx/deltas_spec.rb +12 -12
- data/spec/thinking_sphinx/errors_spec.rb +30 -30
- data/spec/thinking_sphinx/excerpter_spec.rb +7 -7
- data/spec/thinking_sphinx/facet_search_spec.rb +16 -16
- data/spec/thinking_sphinx/index_set_spec.rb +7 -7
- data/spec/thinking_sphinx/index_spec.rb +24 -24
- data/spec/thinking_sphinx/masks/pagination_mask_spec.rb +20 -20
- data/spec/thinking_sphinx/masks/scopes_mask_spec.rb +18 -18
- data/spec/thinking_sphinx/middlewares/active_record_translator_spec.rb +22 -22
- data/spec/thinking_sphinx/middlewares/geographer_spec.rb +9 -9
- data/spec/thinking_sphinx/middlewares/glazier_spec.rb +4 -4
- data/spec/thinking_sphinx/middlewares/inquirer_spec.rb +7 -7
- data/spec/thinking_sphinx/middlewares/sphinxql_spec.rb +53 -53
- data/spec/thinking_sphinx/middlewares/stale_id_checker_spec.rb +5 -5
- data/spec/thinking_sphinx/middlewares/stale_id_filter_spec.rb +15 -15
- data/spec/thinking_sphinx/panes/attributes_pane_spec.rb +1 -1
- data/spec/thinking_sphinx/panes/distance_pane_spec.rb +4 -4
- data/spec/thinking_sphinx/panes/excerpts_pane_spec.rb +5 -5
- data/spec/thinking_sphinx/panes/weight_pane_spec.rb +1 -1
- data/spec/thinking_sphinx/rake_interface_spec.rb +66 -53
- data/spec/thinking_sphinx/real_time/attribute_spec.rb +13 -13
- data/spec/thinking_sphinx/real_time/callbacks/real_time_callbacks_spec.rb +107 -23
- data/spec/thinking_sphinx/real_time/field_spec.rb +14 -14
- data/spec/thinking_sphinx/real_time/index_spec.rb +29 -30
- data/spec/thinking_sphinx/real_time/interpreter_spec.rb +30 -30
- data/spec/thinking_sphinx/scopes_spec.rb +5 -5
- data/spec/thinking_sphinx/search/glaze_spec.rb +15 -15
- data/spec/thinking_sphinx/search/query_spec.rb +10 -10
- data/spec/thinking_sphinx/search_spec.rb +28 -28
- data/spec/thinking_sphinx/wildcard_spec.rb +16 -11
- data/spec/thinking_sphinx_spec.rb +6 -6
- data/thinking-sphinx.gemspec +4 -4
- metadata +12 -9
@@ -7,7 +7,7 @@ describe 'Sorting search results', :live => true do
|
|
7
7
|
boys = Book.create! :title => 'Anansi Boys', :year => 2005
|
8
8
|
index
|
9
9
|
|
10
|
-
Book.search(:order => 'year ASC').to_a.
|
10
|
+
expect(Book.search(:order => 'year ASC').to_a).to eq([gods, boys, grave])
|
11
11
|
end
|
12
12
|
|
13
13
|
it "sorts by a given attribute in ascending order" do
|
@@ -16,7 +16,7 @@ describe 'Sorting search results', :live => true do
|
|
16
16
|
boys = Book.create! :title => 'Anansi Boys', :year => 2005
|
17
17
|
index
|
18
18
|
|
19
|
-
Book.search(:order => :year).to_a.
|
19
|
+
expect(Book.search(:order => :year).to_a).to eq([gods, boys, grave])
|
20
20
|
end
|
21
21
|
|
22
22
|
it "sorts by a given sortable field" do
|
@@ -25,14 +25,14 @@ describe 'Sorting search results', :live => true do
|
|
25
25
|
boys = Book.create! :title => 'Anansi Boys', :year => 2005
|
26
26
|
index
|
27
27
|
|
28
|
-
Book.search(:order => :title).to_a.
|
28
|
+
expect(Book.search(:order => :title).to_a).to eq([gods, boys, grave])
|
29
29
|
end
|
30
30
|
|
31
31
|
it "sorts by a given sortable field with real-time indices" do
|
32
32
|
widgets = Product.create! :name => 'Widgets'
|
33
33
|
gadgets = Product.create! :name => 'Gadgets'
|
34
34
|
|
35
|
-
Product.search(:order => "name_sort ASC").to_a.
|
35
|
+
expect(Product.search(:order => "name_sort ASC").to_a).to eq([gadgets, widgets])
|
36
36
|
end
|
37
37
|
|
38
38
|
it "can sort with a provided expression" do
|
@@ -41,8 +41,8 @@ describe 'Sorting search results', :live => true do
|
|
41
41
|
boys = Book.create! :title => 'Anansi Boys', :year => 2005
|
42
42
|
index
|
43
43
|
|
44
|
-
Book.search(
|
44
|
+
expect(Book.search(
|
45
45
|
:select => '*, year MOD 2004 as mod_year', :order => 'mod_year ASC'
|
46
|
-
).to_a.
|
46
|
+
).to_a).to eq([boys, grave, gods])
|
47
47
|
end
|
48
48
|
end
|
@@ -8,7 +8,7 @@ describe 'specifying SQL for index definitions' do
|
|
8
8
|
join user
|
9
9
|
}
|
10
10
|
index.render
|
11
|
-
index.sources.first.sql_query.
|
11
|
+
expect(index.sources.first.sql_query).to match(/LEFT OUTER JOIN .users./)
|
12
12
|
end
|
13
13
|
|
14
14
|
it "handles deep joins" do
|
@@ -20,8 +20,8 @@ describe 'specifying SQL for index definitions' do
|
|
20
20
|
index.render
|
21
21
|
|
22
22
|
query = index.sources.first.sql_query
|
23
|
-
query.
|
24
|
-
query.
|
23
|
+
expect(query).to match(/LEFT OUTER JOIN .users./)
|
24
|
+
expect(query).to match(/LEFT OUTER JOIN .articles./)
|
25
25
|
end
|
26
26
|
|
27
27
|
it "handles has-many :through joins" do
|
@@ -32,8 +32,8 @@ describe 'specifying SQL for index definitions' do
|
|
32
32
|
index.render
|
33
33
|
|
34
34
|
query = index.sources.first.sql_query
|
35
|
-
query.
|
36
|
-
query.
|
35
|
+
expect(query).to match(/LEFT OUTER JOIN .taggings./)
|
36
|
+
expect(query).to match(/LEFT OUTER JOIN .tags./)
|
37
37
|
end
|
38
38
|
|
39
39
|
it "handles custom join SQL statements" do
|
@@ -45,7 +45,7 @@ describe 'specifying SQL for index definitions' do
|
|
45
45
|
index.render
|
46
46
|
|
47
47
|
query = index.sources.first.sql_query
|
48
|
-
query.
|
48
|
+
expect(query).to match(/INNER JOIN foo ON foo.x = bar.y/)
|
49
49
|
end
|
50
50
|
|
51
51
|
it "handles GROUP BY clauses" do
|
@@ -57,7 +57,7 @@ describe 'specifying SQL for index definitions' do
|
|
57
57
|
index.render
|
58
58
|
|
59
59
|
query = index.sources.first.sql_query
|
60
|
-
query.
|
60
|
+
expect(query).to match(/GROUP BY .articles.\..id., .?articles.?\..title., .?articles.?\..id., lat/)
|
61
61
|
end
|
62
62
|
|
63
63
|
it "handles WHERE clauses" do
|
@@ -69,7 +69,7 @@ describe 'specifying SQL for index definitions' do
|
|
69
69
|
index.render
|
70
70
|
|
71
71
|
query = index.sources.first.sql_query
|
72
|
-
query.
|
72
|
+
expect(query).to match(/WHERE .+title != 'secret'.+ GROUP BY/)
|
73
73
|
end
|
74
74
|
|
75
75
|
it "handles manual MVA declarations" do
|
@@ -81,7 +81,7 @@ describe 'specifying SQL for index definitions' do
|
|
81
81
|
}
|
82
82
|
index.render
|
83
83
|
|
84
|
-
index.sources.first.sql_attr_multi.
|
84
|
+
expect(index.sources.first.sql_attr_multi).to eq(['uint tag_ids from field'])
|
85
85
|
end
|
86
86
|
|
87
87
|
it "provides the sanitize_sql helper within the index definition block" do
|
@@ -93,7 +93,7 @@ describe 'specifying SQL for index definitions' do
|
|
93
93
|
index.render
|
94
94
|
|
95
95
|
query = index.sources.first.sql_query
|
96
|
-
query.
|
96
|
+
expect(query).to match(/WHERE .+title != 'secret'.+ GROUP BY/)
|
97
97
|
end
|
98
98
|
|
99
99
|
it "escapes new lines in SQL snippets" do
|
@@ -111,7 +111,7 @@ describe 'specifying SQL for index definitions' do
|
|
111
111
|
index.render
|
112
112
|
|
113
113
|
query = index.sources.first.sql_query
|
114
|
-
query.
|
114
|
+
expect(query).to match(/\\\n/)
|
115
115
|
end
|
116
116
|
|
117
117
|
it "joins each polymorphic relation" do
|
@@ -123,9 +123,9 @@ describe 'specifying SQL for index definitions' do
|
|
123
123
|
index.render
|
124
124
|
|
125
125
|
query = index.sources.first.sql_query
|
126
|
-
query.
|
127
|
-
query.
|
128
|
-
query.
|
126
|
+
expect(query).to match(/LEFT OUTER JOIN .articles. ON .articles.\..id. = .events.\..eventable_id. AND .events.\..eventable_type. = 'Article'/)
|
127
|
+
expect(query).to match(/LEFT OUTER JOIN .books. ON .books.\..id. = .events.\..eventable_id. AND .events.\..eventable_type. = 'Book'/)
|
128
|
+
expect(query).to match(/.articles.\..title., .books.\..title./)
|
129
129
|
end if ActiveRecord::VERSION::MAJOR > 3
|
130
130
|
|
131
131
|
it "concatenates references that have column" do
|
@@ -137,9 +137,9 @@ describe 'specifying SQL for index definitions' do
|
|
137
137
|
index.render
|
138
138
|
|
139
139
|
query = index.sources.first.sql_query
|
140
|
-
query.
|
141
|
-
query.
|
142
|
-
query.
|
140
|
+
expect(query).to match(/LEFT OUTER JOIN .articles. ON .articles.\..id. = .events.\..eventable_id. AND .events.\..eventable_type. = 'Article'/)
|
141
|
+
expect(query).not_to match(/articles\..title., users\..title./)
|
142
|
+
expect(query).to match(/.articles.\..title./)
|
143
143
|
end if ActiveRecord::VERSION::MAJOR > 3
|
144
144
|
|
145
145
|
it "respects deeper associations through polymorphic joins" do
|
@@ -151,9 +151,9 @@ describe 'specifying SQL for index definitions' do
|
|
151
151
|
index.render
|
152
152
|
|
153
153
|
query = index.sources.first.sql_query
|
154
|
-
query.
|
155
|
-
query.
|
156
|
-
query.
|
154
|
+
expect(query).to match(/LEFT OUTER JOIN .articles. ON .articles.\..id. = .events.\..eventable_id. AND .events.\..eventable_type. = 'Article'/)
|
155
|
+
expect(query).to match(/LEFT OUTER JOIN .users. ON .users.\..id. = .articles.\..user_id./)
|
156
|
+
expect(query).to match(/.users.\..name./)
|
157
157
|
end
|
158
158
|
end if ActiveRecord::VERSION::MAJOR > 3
|
159
159
|
|
@@ -174,8 +174,8 @@ describe 'separate queries for MVAs' do
|
|
174
174
|
}
|
175
175
|
declaration, query = attribute.split(/;\s+/)
|
176
176
|
|
177
|
-
declaration.
|
178
|
-
query.
|
177
|
+
expect(declaration).to eq('uint tag_ids from query')
|
178
|
+
expect(query).to match(/^SELECT .taggings.\..article_id. \* #{count} \+ #{source.offset} AS .id., .taggings.\..tag_id. AS .tag_ids. FROM .taggings.\s? WHERE \(.taggings.\..article_id. IS NOT NULL\)$/)
|
179
179
|
end
|
180
180
|
|
181
181
|
it "generates a SQL query with joins when appropriate for MVAs" do
|
@@ -190,8 +190,8 @@ describe 'separate queries for MVAs' do
|
|
190
190
|
}
|
191
191
|
declaration, query = attribute.split(/;\s+/)
|
192
192
|
|
193
|
-
declaration.
|
194
|
-
query.
|
193
|
+
expect(declaration).to eq('uint tag_ids from query')
|
194
|
+
expect(query).to match(/^SELECT .taggings.\..article_id. \* #{count} \+ #{source.offset} AS .id., .tags.\..id. AS .tag_ids. FROM .taggings. INNER JOIN .tags. ON .tags.\..id. = .taggings.\..tag_id. WHERE \(.taggings.\..article_id. IS NOT NULL\)\s?$/)
|
195
195
|
end
|
196
196
|
|
197
197
|
it "respects has_many :through joins for MVA queries" do
|
@@ -206,8 +206,8 @@ describe 'separate queries for MVAs' do
|
|
206
206
|
}
|
207
207
|
declaration, query = attribute.split(/;\s+/)
|
208
208
|
|
209
|
-
declaration.
|
210
|
-
query.
|
209
|
+
expect(declaration).to eq('uint tag_ids from query')
|
210
|
+
expect(query).to match(/^SELECT .taggings.\..article_id. \* #{count} \+ #{source.offset} AS .id., .tags.\..id. AS .tag_ids. FROM .taggings. INNER JOIN .tags. ON .tags.\..id. = .taggings.\..tag_id. WHERE \(.taggings.\..article_id. IS NOT NULL\)\s?$/)
|
211
211
|
end
|
212
212
|
|
213
213
|
it "can handle multiple joins for MVA queries" do
|
@@ -224,8 +224,8 @@ describe 'separate queries for MVAs' do
|
|
224
224
|
}
|
225
225
|
declaration, query = attribute.split(/;\s+/)
|
226
226
|
|
227
|
-
declaration.
|
228
|
-
query.
|
227
|
+
expect(declaration).to eq('uint tag_ids from query')
|
228
|
+
expect(query).to match(/^SELECT .articles.\..user_id. \* #{count} \+ #{source.offset} AS .id., .tags.\..id. AS .tag_ids. FROM .articles. INNER JOIN .taggings. ON .taggings.\..article_id. = .articles.\..id. INNER JOIN .tags. ON .tags.\..id. = .taggings.\..tag_id. WHERE \(.articles.\..user_id. IS NOT NULL\)\s?$/)
|
229
229
|
end
|
230
230
|
|
231
231
|
it "can handle simple HABTM joins for MVA queries" do
|
@@ -242,8 +242,8 @@ describe 'separate queries for MVAs' do
|
|
242
242
|
}
|
243
243
|
declaration, query = attribute.split(/;\s+/)
|
244
244
|
|
245
|
-
declaration.
|
246
|
-
query.
|
245
|
+
expect(declaration).to eq('uint genre_ids from query')
|
246
|
+
expect(query).to match(/^SELECT .books_genres.\..book_id. \* #{count} \+ #{source.offset} AS .id., .books_genres.\..genre_id. AS .genre_ids. FROM .books_genres.\s?$/)
|
247
247
|
end if ActiveRecord::VERSION::MAJOR > 3
|
248
248
|
|
249
249
|
it "generates an appropriate range SQL queries for an MVA" do
|
@@ -258,9 +258,9 @@ describe 'separate queries for MVAs' do
|
|
258
258
|
}
|
259
259
|
declaration, query, range = attribute.split(/;\s+/)
|
260
260
|
|
261
|
-
declaration.
|
262
|
-
query.
|
263
|
-
range.
|
261
|
+
expect(declaration).to eq('uint tag_ids from ranged-query')
|
262
|
+
expect(query).to match(/^SELECT .taggings.\..article_id. \* #{count} \+ #{source.offset} AS .id., .taggings.\..tag_id. AS .tag_ids. FROM .taggings. \s?WHERE \(.taggings.\..article_id. BETWEEN \$start AND \$end\) AND \(.taggings.\..article_id. IS NOT NULL\)$/)
|
263
|
+
expect(range).to match(/^SELECT MIN\(.taggings.\..article_id.\), MAX\(.taggings.\..article_id.\) FROM .taggings.\s?$/)
|
264
264
|
end
|
265
265
|
|
266
266
|
it "generates a SQL query with joins when appropriate for MVAs" do
|
@@ -275,9 +275,9 @@ describe 'separate queries for MVAs' do
|
|
275
275
|
}
|
276
276
|
declaration, query, range = attribute.split(/;\s+/)
|
277
277
|
|
278
|
-
declaration.
|
279
|
-
query.
|
280
|
-
range.
|
278
|
+
expect(declaration).to eq('uint tag_ids from ranged-query')
|
279
|
+
expect(query).to match(/^SELECT .taggings.\..article_id. \* #{count} \+ #{source.offset} AS .id., .tags.\..id. AS .tag_ids. FROM .taggings. INNER JOIN .tags. ON .tags.\..id. = .taggings.\..tag_id. \s?WHERE \(.taggings.\..article_id. BETWEEN \$start AND \$end\) AND \(.taggings.\..article_id. IS NOT NULL\)$/)
|
280
|
+
expect(range).to match(/^SELECT MIN\(.taggings.\..article_id.\), MAX\(.taggings.\..article_id.\) FROM .taggings.\s?$/)
|
281
281
|
end
|
282
282
|
|
283
283
|
it "can handle ranged queries for simple HABTM joins for MVA queries" do
|
@@ -294,9 +294,9 @@ describe 'separate queries for MVAs' do
|
|
294
294
|
}
|
295
295
|
declaration, query, range = attribute.split(/;\s+/)
|
296
296
|
|
297
|
-
declaration.
|
298
|
-
query.
|
299
|
-
range.
|
297
|
+
expect(declaration).to eq('uint genre_ids from ranged-query')
|
298
|
+
expect(query).to match(/^SELECT .books_genres.\..book_id. \* #{count} \+ #{source.offset} AS .id., .books_genres.\..genre_id. AS .genre_ids. FROM .books_genres. WHERE \(.books_genres.\..book_id. BETWEEN \$start AND \$end\)$/)
|
299
|
+
expect(range).to match(/^SELECT MIN\(.books_genres.\..book_id.\), MAX\(.books_genres.\..book_id.\) FROM .books_genres.$/)
|
300
300
|
end if ActiveRecord::VERSION::MAJOR > 3
|
301
301
|
|
302
302
|
it "respects custom SQL snippets as the query value" do
|
@@ -312,8 +312,8 @@ describe 'separate queries for MVAs' do
|
|
312
312
|
}
|
313
313
|
declaration, query = attribute.split(/;\s+/)
|
314
314
|
|
315
|
-
declaration.
|
316
|
-
query.
|
315
|
+
expect(declaration).to eq('uint tag_ids from query')
|
316
|
+
expect(query).to eq('My Custom SQL Query')
|
317
317
|
end
|
318
318
|
|
319
319
|
it "respects custom SQL snippets as the ranged query value" do
|
@@ -329,9 +329,9 @@ describe 'separate queries for MVAs' do
|
|
329
329
|
}
|
330
330
|
declaration, query, range = attribute.split(/;\s+/)
|
331
331
|
|
332
|
-
declaration.
|
333
|
-
query.
|
334
|
-
range.
|
332
|
+
expect(declaration).to eq('uint tag_ids from ranged-query')
|
333
|
+
expect(query).to eq('My Custom SQL Query')
|
334
|
+
expect(range).to eq('And a Range')
|
335
335
|
end
|
336
336
|
|
337
337
|
it "escapes new lines in custom SQL snippets" do
|
@@ -349,8 +349,8 @@ SQL Query
|
|
349
349
|
}
|
350
350
|
declaration, query = attribute.split(/;\s+/)
|
351
351
|
|
352
|
-
declaration.
|
353
|
-
query.
|
352
|
+
expect(declaration).to eq('uint tag_ids from query')
|
353
|
+
expect(query).to eq("My Custom\\\nSQL Query")
|
354
354
|
end
|
355
355
|
end
|
356
356
|
|
@@ -368,8 +368,8 @@ describe 'separate queries for field' do
|
|
368
368
|
field = source.sql_joined_field.detect { |field| field[/tags/] }
|
369
369
|
declaration, query = field.split(/;\s+/)
|
370
370
|
|
371
|
-
declaration.
|
372
|
-
query.
|
371
|
+
expect(declaration).to eq('tags from query')
|
372
|
+
expect(query).to match(/^SELECT .taggings.\..article_id. \* #{count} \+ #{source.offset} AS .id., .tags.\..name. AS .tags. FROM .taggings. INNER JOIN .tags. ON .tags.\..id. = .taggings.\..tag_id.\s? WHERE \(.taggings.\..article_id. IS NOT NULL\)\s? ORDER BY .taggings.\..article_id. ASC\s?$/)
|
373
373
|
end
|
374
374
|
|
375
375
|
it "respects has_many :through joins for MVF queries" do
|
@@ -381,8 +381,8 @@ describe 'separate queries for field' do
|
|
381
381
|
field = source.sql_joined_field.detect { |field| field[/tags/] }
|
382
382
|
declaration, query = field.split(/;\s+/)
|
383
383
|
|
384
|
-
declaration.
|
385
|
-
query.
|
384
|
+
expect(declaration).to eq('tags from query')
|
385
|
+
expect(query).to match(/^SELECT .taggings.\..article_id. \* #{count} \+ #{source.offset} AS .id., .tags.\..name. AS .tags. FROM .taggings. INNER JOIN .tags. ON .tags.\..id. = .taggings.\..tag_id.\s? WHERE \(.taggings.\..article_id. IS NOT NULL\)\s? ORDER BY .taggings.\..article_id. ASC\s?$/)
|
386
386
|
end
|
387
387
|
|
388
388
|
it "can handle multiple joins for MVF queries" do
|
@@ -396,8 +396,8 @@ describe 'separate queries for field' do
|
|
396
396
|
field = source.sql_joined_field.detect { |field| field[/tags/] }
|
397
397
|
declaration, query = field.split(/;\s+/)
|
398
398
|
|
399
|
-
declaration.
|
400
|
-
query.
|
399
|
+
expect(declaration).to eq('tags from query')
|
400
|
+
expect(query).to match(/^SELECT .articles.\..user_id. \* #{count} \+ #{source.offset} AS .id., .tags.\..name. AS .tags. FROM .articles. INNER JOIN .taggings. ON .taggings.\..article_id. = .articles.\..id. INNER JOIN .tags. ON .tags.\..id. = .taggings.\..tag_id.\s? WHERE \(.articles.\..user_id. IS NOT NULL\)\s? ORDER BY .articles.\..user_id. ASC\s?$/)
|
401
401
|
end
|
402
402
|
|
403
403
|
it "generates a SQL query with joins when appropriate for MVFs" do
|
@@ -409,9 +409,9 @@ describe 'separate queries for field' do
|
|
409
409
|
field = source.sql_joined_field.detect { |field| field[/tags/] }
|
410
410
|
declaration, query, range = field.split(/;\s+/)
|
411
411
|
|
412
|
-
declaration.
|
413
|
-
query.
|
414
|
-
range.
|
412
|
+
expect(declaration).to eq('tags from ranged-query')
|
413
|
+
expect(query).to match(/^SELECT .taggings.\..article_id. \* #{count} \+ #{source.offset} AS .id., .tags.\..name. AS .tags. FROM .taggings. INNER JOIN .tags. ON .tags.\..id. = .taggings.\..tag_id. \s?WHERE \(.taggings.\..article_id. BETWEEN \$start AND \$end\) AND \(.taggings.\..article_id. IS NOT NULL\)\s? ORDER BY .taggings.\..article_id. ASC$/)
|
414
|
+
expect(range).to match(/^SELECT MIN\(.taggings.\..article_id.\), MAX\(.taggings.\..article_id.\) FROM .taggings.\s?$/)
|
415
415
|
end
|
416
416
|
|
417
417
|
it "respects custom SQL snippets as the query value" do
|
@@ -423,8 +423,8 @@ describe 'separate queries for field' do
|
|
423
423
|
field = source.sql_joined_field.detect { |field| field[/tags/] }
|
424
424
|
declaration, query = field.split(/;\s+/)
|
425
425
|
|
426
|
-
declaration.
|
427
|
-
query.
|
426
|
+
expect(declaration).to eq('tags from query')
|
427
|
+
expect(query).to eq('My Custom SQL Query')
|
428
428
|
end
|
429
429
|
|
430
430
|
it "respects custom SQL snippets as the ranged query value" do
|
@@ -437,9 +437,9 @@ describe 'separate queries for field' do
|
|
437
437
|
field = source.sql_joined_field.detect { |field| field[/tags/] }
|
438
438
|
declaration, query, range = field.split(/;\s+/)
|
439
439
|
|
440
|
-
declaration.
|
441
|
-
query.
|
442
|
-
range.
|
440
|
+
expect(declaration).to eq('tags from ranged-query')
|
441
|
+
expect(query).to eq('My Custom SQL Query')
|
442
|
+
expect(range).to eq('And a Range')
|
443
443
|
end
|
444
444
|
|
445
445
|
it "escapes new lines in custom SQL snippets" do
|
@@ -454,7 +454,7 @@ SQL Query
|
|
454
454
|
field = source.sql_joined_field.detect { |field| field[/tags/] }
|
455
455
|
declaration, query = field.split(/;\s+/)
|
456
456
|
|
457
|
-
declaration.
|
458
|
-
query.
|
457
|
+
expect(declaration).to eq('tags from query')
|
458
|
+
expect(query).to eq("My Custom\\\nSQL Query")
|
459
459
|
end
|
460
460
|
end
|
@@ -7,7 +7,7 @@ describe 'Sphinx scopes', :live => true do
|
|
7
7
|
grave = Book.create! :title => 'The Graveyard Book', :year => 2009
|
8
8
|
index
|
9
9
|
|
10
|
-
Book.by_year(2009).to_a.
|
10
|
+
expect(Book.by_year(2009).to_a).to eq([grave])
|
11
11
|
end
|
12
12
|
|
13
13
|
it "allows scopes to return both query and options" do
|
@@ -16,7 +16,7 @@ describe 'Sphinx scopes', :live => true do
|
|
16
16
|
grave = Book.create! :title => 'The Graveyard Book', :year => 2009
|
17
17
|
index
|
18
18
|
|
19
|
-
Book.by_query_and_year('Graveyard', 2009).to_a.
|
19
|
+
expect(Book.by_query_and_year('Graveyard', 2009).to_a).to eq([grave])
|
20
20
|
end
|
21
21
|
|
22
22
|
it "allows chaining of scopes" do
|
@@ -25,7 +25,7 @@ describe 'Sphinx scopes', :live => true do
|
|
25
25
|
grave = Book.create! :title => 'The Graveyard Book', :year => 2009
|
26
26
|
index
|
27
27
|
|
28
|
-
Book.by_year(2001..2005).ordered.to_a.
|
28
|
+
expect(Book.by_year(2001..2005).ordered.to_a).to eq([boys, gods])
|
29
29
|
end
|
30
30
|
|
31
31
|
it "allows chaining of scopes that include queries" do
|
@@ -34,8 +34,8 @@ describe 'Sphinx scopes', :live => true do
|
|
34
34
|
grave = Book.create! :title => 'The Graveyard Book', :year => 2009
|
35
35
|
index
|
36
36
|
|
37
|
-
Book.by_year(2001).by_query_and_year('Graveyard', 2009).to_a.
|
38
|
-
|
37
|
+
expect(Book.by_year(2001).by_query_and_year('Graveyard', 2009).to_a).
|
38
|
+
to eq([grave])
|
39
39
|
end
|
40
40
|
|
41
41
|
it "allows further search calls on scopes" do
|
@@ -43,7 +43,7 @@ describe 'Sphinx scopes', :live => true do
|
|
43
43
|
pratchett = Book.create! :title => 'Small Gods'
|
44
44
|
index
|
45
45
|
|
46
|
-
Book.by_query('Gods').search('Small').to_a.
|
46
|
+
expect(Book.by_query('Gods').search('Small').to_a).to eq([pratchett])
|
47
47
|
end
|
48
48
|
|
49
49
|
it "allows facet calls on scopes" do
|
@@ -52,9 +52,9 @@ describe 'Sphinx scopes', :live => true do
|
|
52
52
|
Book.create! :title => 'Small Gods', :author => 'Terry Pratchett'
|
53
53
|
index
|
54
54
|
|
55
|
-
Book.by_query('Gods').facets.to_hash[:author].
|
55
|
+
expect(Book.by_query('Gods').facets.to_hash[:author]).to eq({
|
56
56
|
'Neil Gaiman' => 1, 'Terry Pratchett' => 1
|
57
|
-
}
|
57
|
+
})
|
58
58
|
end
|
59
59
|
|
60
60
|
it "allows accessing counts on scopes" do
|
@@ -64,7 +64,7 @@ describe 'Sphinx scopes', :live => true do
|
|
64
64
|
Book.create! :title => 'Night Watch'
|
65
65
|
index
|
66
66
|
|
67
|
-
Book.by_query('gods').count.
|
67
|
+
expect(Book.by_query('gods').count).to eq(2)
|
68
68
|
end
|
69
69
|
|
70
70
|
it 'raises an exception when trying to modify a populated request' do
|
@@ -7,38 +7,38 @@ describe 'SQL delta indexing', :live => true do
|
|
7
7
|
)
|
8
8
|
index
|
9
9
|
|
10
|
-
Book.search('Terry Pratchett').to_a.
|
10
|
+
expect(Book.search('Terry Pratchett').to_a).to eq([guards])
|
11
11
|
|
12
12
|
men = Book.create(
|
13
13
|
:title => 'Men At Arms', :author => 'Terry Pratchett'
|
14
14
|
)
|
15
15
|
sleep 0.25
|
16
16
|
|
17
|
-
Book.search('Terry Pratchett').to_a.
|
17
|
+
expect(Book.search('Terry Pratchett').to_a).to eq([guards, men])
|
18
18
|
end
|
19
19
|
|
20
20
|
it "automatically indexes updated records" do
|
21
21
|
book = Book.create :title => 'Night Watch', :author => 'Harry Pritchett'
|
22
22
|
index
|
23
23
|
|
24
|
-
Book.search('Harry').to_a.
|
24
|
+
expect(Book.search('Harry').to_a).to eq([book])
|
25
25
|
|
26
26
|
book.reload.update_attributes(:author => 'Terry Pratchett')
|
27
27
|
sleep 0.25
|
28
28
|
|
29
|
-
Book.search('Terry').to_a.
|
29
|
+
expect(Book.search('Terry').to_a).to eq([book])
|
30
30
|
end
|
31
31
|
|
32
32
|
it "does not match on old values" do
|
33
33
|
book = Book.create :title => 'Night Watch', :author => 'Harry Pritchett'
|
34
34
|
index
|
35
35
|
|
36
|
-
Book.search('Harry').to_a.
|
36
|
+
expect(Book.search('Harry').to_a).to eq([book])
|
37
37
|
|
38
38
|
book.reload.update_attributes(:author => 'Terry Pratchett')
|
39
39
|
sleep 0.25
|
40
40
|
|
41
|
-
Book.search('Harry').
|
41
|
+
expect(Book.search('Harry')).to be_empty
|
42
42
|
end
|
43
43
|
|
44
44
|
it "automatically indexes new records of subclasses" do
|
@@ -47,6 +47,6 @@ describe 'SQL delta indexing', :live => true do
|
|
47
47
|
)
|
48
48
|
sleep 0.25
|
49
49
|
|
50
|
-
Book.search('Gaiman').to_a.
|
50
|
+
expect(Book.search('Gaiman').to_a).to eq([book])
|
51
51
|
end
|
52
52
|
end
|