DrMark-thinking-sphinx 1.1.15 → 1.2.5

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.
Files changed (63) hide show
  1. data/README.textile +22 -0
  2. data/VERSION.yml +4 -0
  3. data/lib/thinking_sphinx/active_record/scopes.rb +39 -0
  4. data/lib/thinking_sphinx/active_record.rb +27 -7
  5. data/lib/thinking_sphinx/adapters/postgresql_adapter.rb +9 -3
  6. data/lib/thinking_sphinx/association.rb +4 -1
  7. data/lib/thinking_sphinx/attribute.rb +91 -30
  8. data/lib/thinking_sphinx/configuration.rb +51 -12
  9. data/lib/thinking_sphinx/deltas/datetime_delta.rb +2 -2
  10. data/lib/thinking_sphinx/deltas/default_delta.rb +1 -1
  11. data/lib/thinking_sphinx/deltas/delayed_delta/delta_job.rb +1 -1
  12. data/lib/thinking_sphinx/deltas/delayed_delta.rb +3 -0
  13. data/lib/thinking_sphinx/deploy/capistrano.rb +25 -8
  14. data/lib/thinking_sphinx/excerpter.rb +22 -0
  15. data/lib/thinking_sphinx/facet.rb +1 -1
  16. data/lib/thinking_sphinx/facet_search.rb +134 -0
  17. data/lib/thinking_sphinx/index.rb +2 -1
  18. data/lib/thinking_sphinx/rails_additions.rb +14 -0
  19. data/lib/thinking_sphinx/search.rb +599 -658
  20. data/lib/thinking_sphinx/search_methods.rb +421 -0
  21. data/lib/thinking_sphinx/source/internal_properties.rb +1 -1
  22. data/lib/thinking_sphinx/source/sql.rb +17 -13
  23. data/lib/thinking_sphinx/source.rb +6 -6
  24. data/lib/thinking_sphinx/tasks.rb +42 -8
  25. data/lib/thinking_sphinx.rb +82 -54
  26. data/rails/init.rb +14 -0
  27. data/spec/{unit → lib}/thinking_sphinx/active_record/delta_spec.rb +5 -5
  28. data/spec/{unit → lib}/thinking_sphinx/active_record/has_many_association_spec.rb +0 -0
  29. data/spec/lib/thinking_sphinx/active_record/scopes_spec.rb +96 -0
  30. data/spec/{unit → lib}/thinking_sphinx/active_record_spec.rb +51 -31
  31. data/spec/{unit → lib}/thinking_sphinx/association_spec.rb +4 -5
  32. data/spec/lib/thinking_sphinx/attribute_spec.rb +465 -0
  33. data/spec/{unit → lib}/thinking_sphinx/configuration_spec.rb +161 -29
  34. data/spec/{unit → lib}/thinking_sphinx/core/string_spec.rb +0 -0
  35. data/spec/lib/thinking_sphinx/excerpter_spec.rb +49 -0
  36. data/spec/lib/thinking_sphinx/facet_search_spec.rb +176 -0
  37. data/spec/{unit → lib}/thinking_sphinx/facet_spec.rb +24 -0
  38. data/spec/{unit → lib}/thinking_sphinx/field_spec.rb +8 -8
  39. data/spec/{unit → lib}/thinking_sphinx/index/builder_spec.rb +6 -2
  40. data/spec/{unit → lib}/thinking_sphinx/index/faux_column_spec.rb +0 -0
  41. data/spec/lib/thinking_sphinx/index_spec.rb +45 -0
  42. data/spec/{unit → lib}/thinking_sphinx/rails_additions_spec.rb +25 -5
  43. data/spec/lib/thinking_sphinx/search_methods_spec.rb +152 -0
  44. data/spec/lib/thinking_sphinx/search_spec.rb +960 -0
  45. data/spec/{unit → lib}/thinking_sphinx/source_spec.rb +63 -2
  46. data/spec/{unit → lib}/thinking_sphinx_spec.rb +32 -4
  47. data/tasks/distribution.rb +36 -35
  48. data/vendor/riddle/lib/riddle/client/message.rb +4 -3
  49. data/vendor/riddle/lib/riddle/client.rb +3 -0
  50. data/vendor/riddle/lib/riddle/configuration/section.rb +8 -2
  51. data/vendor/riddle/lib/riddle/controller.rb +17 -7
  52. data/vendor/riddle/lib/riddle.rb +1 -1
  53. metadata +79 -83
  54. data/lib/thinking_sphinx/active_record/search.rb +0 -57
  55. data/lib/thinking_sphinx/collection.rb +0 -148
  56. data/lib/thinking_sphinx/facet_collection.rb +0 -59
  57. data/lib/thinking_sphinx/search/facets.rb +0 -98
  58. data/spec/unit/thinking_sphinx/active_record/search_spec.rb +0 -107
  59. data/spec/unit/thinking_sphinx/attribute_spec.rb +0 -232
  60. data/spec/unit/thinking_sphinx/collection_spec.rb +0 -14
  61. data/spec/unit/thinking_sphinx/facet_collection_spec.rb +0 -64
  62. data/spec/unit/thinking_sphinx/index_spec.rb +0 -139
  63. data/spec/unit/thinking_sphinx/search_spec.rb +0 -130
@@ -0,0 +1,465 @@
1
+ require 'spec/spec_helper'
2
+
3
+ describe ThinkingSphinx::Attribute do
4
+ before :each do
5
+ @index = ThinkingSphinx::Index.new(Person)
6
+ @source = ThinkingSphinx::Source.new(@index)
7
+
8
+ @index.delta_object = ThinkingSphinx::Deltas::DefaultDelta.new @index, @index.local_options
9
+ end
10
+
11
+ describe '#initialize' do
12
+ it 'raises if no columns are provided so that configuration errors are easier to track down' do
13
+ lambda {
14
+ ThinkingSphinx::Attribute.new(@source, [])
15
+ }.should raise_error(RuntimeError)
16
+ end
17
+
18
+ it 'raises if an element of the columns param is an integer - as happens when you use id instead of :id - so that configuration errors are easier to track down' do
19
+ lambda {
20
+ ThinkingSphinx::Attribute.new(@source, [1234])
21
+ }.should raise_error(RuntimeError)
22
+ end
23
+ end
24
+
25
+ describe "unique_name method" do
26
+ before :each do
27
+ @attribute = ThinkingSphinx::Attribute.new @source, [
28
+ Object.stub_instance(:__stack => [], :__name => "col_name")
29
+ ]
30
+ end
31
+
32
+ it "should use the alias if there is one" do
33
+ @attribute.alias = "alias"
34
+ @attribute.unique_name.should == "alias"
35
+ end
36
+
37
+ it "should use the alias if there's multiple columns" do
38
+ @attribute.columns << Object.stub_instance(:__stack => [], :__name => "col_name")
39
+ @attribute.unique_name.should be_nil
40
+
41
+ @attribute.alias = "alias"
42
+ @attribute.unique_name.should == "alias"
43
+ end
44
+
45
+ it "should use the column name if there's no alias and just one column" do
46
+ @attribute.unique_name.should == "col_name"
47
+ end
48
+ end
49
+
50
+ describe "column_with_prefix method" do
51
+ before :each do
52
+ @attribute = ThinkingSphinx::Attribute.new @source, [
53
+ ThinkingSphinx::Index::FauxColumn.new(:col_name)
54
+ ]
55
+ @attribute.columns.each { |col| @attribute.associations[col] = [] }
56
+ @attribute.model = Person
57
+
58
+ @first_join = Object.new
59
+ @first_join.stub!(:aliased_table_name => "tabular")
60
+ @second_join = Object.new
61
+ @second_join.stub!(:aliased_table_name => "data")
62
+
63
+ @first_assoc = ThinkingSphinx::Association.new nil, nil
64
+ @first_assoc.stub!(:join => @first_join, :has_column? => true)
65
+ @second_assoc = ThinkingSphinx::Association.new nil, nil
66
+ @second_assoc.stub!(:join => @second_join, :has_column? => true)
67
+ end
68
+
69
+ it "should return the column name if the column is a string" do
70
+ @attribute.columns = [ThinkingSphinx::Index::FauxColumn.new("string")]
71
+ @attribute.send(:column_with_prefix, @attribute.columns.first).should == "string"
72
+ end
73
+
74
+ it "should return the column with model's table prefix if there's no associations for the column" do
75
+ @attribute.send(:column_with_prefix, @attribute.columns.first).should == "`people`.`col_name`"
76
+ end
77
+
78
+ it "should return the column with its join table prefix if an association exists" do
79
+ column = @attribute.columns.first
80
+ @attribute.associations[column] = [@first_assoc]
81
+ @attribute.send(:column_with_prefix, column).should == "`tabular`.`col_name`"
82
+ end
83
+
84
+ it "should return multiple columns concatenated if more than one association exists" do
85
+ column = @attribute.columns.first
86
+ @attribute.associations[column] = [@first_assoc, @second_assoc]
87
+ @attribute.send(:column_with_prefix, column).should == "`tabular`.`col_name`, `data`.`col_name`"
88
+ end
89
+ end
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
+
104
+ describe "is_many? method" do
105
+ before :each do
106
+ @assoc_a = Object.stub_instance(:is_many? => true)
107
+ @assoc_b = Object.stub_instance(:is_many? => true)
108
+ @assoc_c = Object.stub_instance(:is_many? => true)
109
+
110
+ @attribute = ThinkingSphinx::Attribute.new(
111
+ @source, [ThinkingSphinx::Index::FauxColumn.new(:col_name)]
112
+ )
113
+ @attribute.associations = {
114
+ :a => @assoc_a, :b => @assoc_b, :c => @assoc_c
115
+ }
116
+ end
117
+
118
+ it "should return true if all associations return true to is_many?" do
119
+ @attribute.send(:is_many?).should be_true
120
+ end
121
+
122
+ it "should return true if one association returns true to is_many?" do
123
+ @assoc_b.stub_method(:is_many? => false)
124
+ @assoc_c.stub_method(:is_many? => false)
125
+
126
+ @attribute.send(:is_many?).should be_true
127
+ end
128
+
129
+ it "should return false if all associations return false to is_many?" do
130
+ @assoc_a.stub_method(:is_many? => false)
131
+ @assoc_b.stub_method(:is_many? => false)
132
+ @assoc_c.stub_method(:is_many? => false)
133
+
134
+ @attribute.send(:is_many?).should be_false
135
+ end
136
+ end
137
+
138
+ describe "is_string? method" do
139
+ before :each do
140
+ @col_a = ThinkingSphinx::Index::FauxColumn.new("a")
141
+ @col_b = ThinkingSphinx::Index::FauxColumn.new("b")
142
+ @col_c = ThinkingSphinx::Index::FauxColumn.new("c")
143
+
144
+ @attribute = ThinkingSphinx::Attribute.new(
145
+ @source, [@col_a, @col_b, @col_c]
146
+ )
147
+ end
148
+
149
+ it "should return true if all columns return true to is_string?" do
150
+ @attribute.send(:is_string?).should be_true
151
+ end
152
+
153
+ it "should return false if one column returns true to is_string?" do
154
+ @col_a.send(:instance_variable_set, :@name, :a)
155
+ @attribute.send(:is_string?).should be_false
156
+ end
157
+
158
+ it "should return false if all columns return false to is_string?" do
159
+ @col_a.send(:instance_variable_set, :@name, :a)
160
+ @col_b.send(:instance_variable_set, :@name, :b)
161
+ @col_c.send(:instance_variable_set, :@name, :c)
162
+ @attribute.send(:is_string?).should be_false
163
+ end
164
+ end
165
+
166
+ describe "type method" do
167
+ before :each do
168
+ @column = ThinkingSphinx::Index::FauxColumn.new(:col_name)
169
+ @attribute = ThinkingSphinx::Attribute.new(@source, [@column])
170
+ @attribute.model = Person
171
+ @attribute.stub_method(:is_many? => false)
172
+ end
173
+
174
+ it "should return :multi if is_many? is true" do
175
+ @attribute.stub_method(:is_many? => true)
176
+ @attribute.send(:type).should == :multi
177
+ end
178
+
179
+ it "should return :string if there's more than one association" do
180
+ @attribute.associations = {:a => [:assoc], :b => [:assoc]}
181
+ @attribute.send(:type).should == :string
182
+ end
183
+
184
+ it "should return the column type from the database if not :multi or more than one association" do
185
+ @column.send(:instance_variable_set, :@name, "birthday")
186
+ @attribute.send(:type).should == :datetime
187
+
188
+ @attribute.send(:instance_variable_set, :@type, nil)
189
+ @column.send(:instance_variable_set, :@name, "first_name")
190
+ @attribute.send(:type).should == :string
191
+
192
+ @attribute.send(:instance_variable_set, :@type, nil)
193
+ @column.send(:instance_variable_set, :@name, "id")
194
+ @attribute.send(:type).should == :integer
195
+ end
196
+ end
197
+
198
+ describe "all_ints? method" do
199
+ it "should return true if all columns are integers" do
200
+ attribute = ThinkingSphinx::Attribute.new(@source,
201
+ [ ThinkingSphinx::Index::FauxColumn.new(:id),
202
+ ThinkingSphinx::Index::FauxColumn.new(:team_id) ]
203
+ )
204
+ attribute.model = Person
205
+ attribute.columns.each { |col| attribute.associations[col] = [] }
206
+
207
+ attribute.should be_all_ints
208
+ end
209
+
210
+ it "should return false if only some columns are integers" do
211
+ attribute = ThinkingSphinx::Attribute.new(@source,
212
+ [ ThinkingSphinx::Index::FauxColumn.new(:id),
213
+ ThinkingSphinx::Index::FauxColumn.new(:first_name) ]
214
+ )
215
+ attribute.model = Person
216
+ attribute.columns.each { |col| attribute.associations[col] = [] }
217
+
218
+ attribute.should_not be_all_ints
219
+ end
220
+
221
+ it "should return false if no columns are integers" do
222
+ attribute = ThinkingSphinx::Attribute.new(@source,
223
+ [ ThinkingSphinx::Index::FauxColumn.new(:first_name),
224
+ ThinkingSphinx::Index::FauxColumn.new(:last_name) ]
225
+ )
226
+ attribute.model = Person
227
+ attribute.columns.each { |col| attribute.associations[col] = [] }
228
+
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
265
+ end
266
+ end
267
+
268
+ describe "MVA with source query" do
269
+ before :each do
270
+ @attribute = ThinkingSphinx::Attribute.new(@source,
271
+ [ThinkingSphinx::Index::FauxColumn.new(:tags, :id)],
272
+ :as => :tag_ids, :source => :query
273
+ )
274
+ end
275
+
276
+ it "should use a query" do
277
+ @attribute.type_to_config.should == :sql_attr_multi
278
+
279
+ declaration, query = @attribute.config_value.split('; ')
280
+ declaration.should == "uint tag_ids from query"
281
+ query.should == "SELECT `tags`.`person_id` #{ThinkingSphinx.unique_id_expression} AS `id`, `tags`.`id` AS `tag_ids` FROM `tags`"
282
+ end
283
+ end
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
+
302
+ describe "MVA via a HABTM association with a source query" do
303
+ before :each do
304
+ @attribute = ThinkingSphinx::Attribute.new(@source,
305
+ [ThinkingSphinx::Index::FauxColumn.new(:links, :id)],
306
+ :as => :link_ids, :source => :query
307
+ )
308
+ end
309
+
310
+ it "should use a ranged query" do
311
+ @attribute.type_to_config.should == :sql_attr_multi
312
+
313
+ declaration, query = @attribute.config_value.split('; ')
314
+ declaration.should == "uint link_ids from query"
315
+ query.should == "SELECT `links_people`.`person_id` #{ThinkingSphinx.unique_id_expression} AS `id`, `links_people`.`link_id` AS `link_ids` FROM `links_people`"
316
+ end
317
+ end
318
+
319
+ describe "MVA with ranged source query" do
320
+ before :each do
321
+ @attribute = ThinkingSphinx::Attribute.new(@source,
322
+ [ThinkingSphinx::Index::FauxColumn.new(:tags, :id)],
323
+ :as => :tag_ids, :source => :ranged_query
324
+ )
325
+ end
326
+
327
+ it "should use a ranged query" do
328
+ @attribute.type_to_config.should == :sql_attr_multi
329
+
330
+ declaration, query, range_query = @attribute.config_value.split('; ')
331
+ declaration.should == "uint tag_ids from ranged-query"
332
+ 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"
333
+ range_query.should == "SELECT MIN(`tags`.`person_id`), MAX(`tags`.`person_id`) FROM `tags`"
334
+ end
335
+ end
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
+
355
+ describe "MVA via a has-many :through with a ranged source query" do
356
+ before :each do
357
+ @attribute = ThinkingSphinx::Attribute.new(@source,
358
+ [ThinkingSphinx::Index::FauxColumn.new(:football_teams, :id)],
359
+ :as => :football_team_ids, :source => :ranged_query
360
+ )
361
+ end
362
+
363
+ it "should use a ranged query" do
364
+ @attribute.type_to_config.should == :sql_attr_multi
365
+
366
+ declaration, query, range_query = @attribute.config_value.split('; ')
367
+ declaration.should == "uint football_team_ids from ranged-query"
368
+ query.should == "SELECT `tags`.`person_id` #{ThinkingSphinx.unique_id_expression} AS `id`, `tags`.`football_team_id` AS `football_team_ids` FROM `tags` WHERE `tags`.`person_id` >= $start AND `tags`.`person_id` <= $end"
369
+ range_query.should == "SELECT MIN(`tags`.`person_id`), MAX(`tags`.`person_id`) FROM `tags`"
370
+ end
371
+ end
372
+
373
+ describe "MVA via a has-many :through using a foreign key with a ranged source query" do
374
+ before :each do
375
+ @attribute = ThinkingSphinx::Attribute.new(@source,
376
+ [ThinkingSphinx::Index::FauxColumn.new(:friends, :id)],
377
+ :as => :friend_ids, :source => :ranged_query
378
+ )
379
+ end
380
+
381
+ it "should use a ranged query" do
382
+ @attribute.type_to_config.should == :sql_attr_multi
383
+
384
+ declaration, query, range_query = @attribute.config_value.split('; ')
385
+ declaration.should == "uint friend_ids from ranged-query"
386
+ query.should == "SELECT `friendships`.`person_id` #{ThinkingSphinx.unique_id_expression} AS `id`, `friendships`.`friend_id` AS `friend_ids` FROM `friendships` WHERE `friendships`.`person_id` >= $start AND `friendships`.`person_id` <= $end"
387
+ range_query.should == "SELECT MIN(`friendships`.`person_id`), MAX(`friendships`.`person_id`) FROM `friendships`"
388
+ end
389
+ end
390
+
391
+ describe "MVA via a HABTM with a ranged source query" do
392
+ before :each do
393
+ @attribute = ThinkingSphinx::Attribute.new(@source,
394
+ [ThinkingSphinx::Index::FauxColumn.new(:links, :id)],
395
+ :as => :link_ids, :source => :ranged_query
396
+ )
397
+ end
398
+
399
+ it "should use a ranged query" do
400
+ @attribute.type_to_config.should == :sql_attr_multi
401
+
402
+ declaration, query, range_query = @attribute.config_value.split('; ')
403
+ declaration.should == "uint link_ids from ranged-query"
404
+ query.should == "SELECT `links_people`.`person_id` #{ThinkingSphinx.unique_id_expression} AS `id`, `links_people`.`link_id` AS `link_ids` FROM `links_people` WHERE `links_people`.`person_id` >= $start AND `links_people`.`person_id` <= $end"
405
+ range_query.should == "SELECT MIN(`links_people`.`person_id`), MAX(`links_people`.`person_id`) FROM `links_people`"
406
+ end
407
+ end
408
+
409
+ describe "MVA via two has-many associations with a ranged source query" do
410
+ before :each do
411
+ @index = ThinkingSphinx::Index.new(Alpha)
412
+ @source = ThinkingSphinx::Source.new(@index)
413
+ @attribute = ThinkingSphinx::Attribute.new(@source,
414
+ [ThinkingSphinx::Index::FauxColumn.new(:betas, :gammas, :value)],
415
+ :as => :gamma_values, :source => :ranged_query
416
+ )
417
+ end
418
+
419
+ it "should use a ranged query" do
420
+ @attribute.type_to_config.should == :sql_attr_multi
421
+
422
+ declaration, query, range_query = @attribute.config_value.split('; ')
423
+ declaration.should == "uint gamma_values from ranged-query"
424
+ 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"
425
+ range_query.should == "SELECT MIN(`betas`.`alpha_id`), MAX(`betas`.`alpha_id`) FROM `betas`"
426
+ end
427
+ end
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
+
451
+ describe "with custom queries" do
452
+ before :each do
453
+ index = CricketTeam.sphinx_indexes.first
454
+ @statement = index.sources.first.to_riddle_for_core(0, 0).sql_attr_multi.last
455
+ end
456
+
457
+ it "should track the query type accordingly" do
458
+ @statement.should match(/uint tags from query/)
459
+ end
460
+
461
+ it "should include the SQL statement" do
462
+ @statement.should match(/SELECT cricket_team_id, id FROM tags/)
463
+ end
464
+ end
465
+ end