sphinx 0.9.10.2122 → 2.1.1.3711

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 (185) hide show
  1. data/.gitignore +5 -2
  2. data/.travis.yml +8 -0
  3. data/CHANGELOG.md +71 -0
  4. data/Gemfile +4 -0
  5. data/README.md +221 -0
  6. data/Rakefile +40 -35
  7. data/lib/sphinx.rb +3 -8
  8. data/lib/sphinx/client.rb +223 -70
  9. data/lib/sphinx/constants.rb +23 -8
  10. data/lib/sphinx/response.rb +6 -6
  11. data/lib/sphinx/timeout.rb +1 -2
  12. data/lib/sphinx/version.rb +3 -0
  13. data/spec/client_response_spec.rb +77 -64
  14. data/spec/client_spec.rb +68 -31
  15. data/spec/client_validations_spec.rb +61 -7
  16. data/spec/fixtures/requests/default_search.dat +0 -0
  17. data/spec/fixtures/requests/default_search_index.dat +0 -0
  18. data/spec/fixtures/requests/excerpt_custom.dat +0 -0
  19. data/spec/fixtures/requests/excerpt_default.dat +0 -0
  20. data/spec/fixtures/requests/excerpt_flags.dat +0 -0
  21. data/spec/fixtures/requests/field_weights.dat +0 -0
  22. data/spec/fixtures/requests/filter.dat +0 -0
  23. data/spec/fixtures/requests/filter_exclude.dat +0 -0
  24. data/spec/fixtures/requests/filter_float_range.dat +0 -0
  25. data/spec/fixtures/requests/filter_float_range_exclude.dat +0 -0
  26. data/spec/fixtures/requests/filter_range.dat +0 -0
  27. data/spec/fixtures/requests/filter_range_exclude.dat +0 -0
  28. data/spec/fixtures/requests/filter_range_int64.dat +0 -0
  29. data/spec/fixtures/requests/filter_ranges.dat +0 -0
  30. data/spec/fixtures/requests/filters.dat +0 -0
  31. data/spec/fixtures/requests/filters_different.dat +0 -0
  32. data/spec/fixtures/requests/geo_anchor.dat +0 -0
  33. data/spec/fixtures/requests/group_by_attr.dat +0 -0
  34. data/spec/fixtures/requests/group_by_attrpair.dat +0 -0
  35. data/spec/fixtures/requests/group_by_day.dat +0 -0
  36. data/spec/fixtures/requests/group_by_day_sort.dat +0 -0
  37. data/spec/fixtures/requests/group_by_month.dat +0 -0
  38. data/spec/fixtures/requests/group_by_week.dat +0 -0
  39. data/spec/fixtures/requests/group_by_year.dat +0 -0
  40. data/spec/fixtures/requests/group_distinct.dat +0 -0
  41. data/spec/fixtures/requests/id_range.dat +0 -0
  42. data/spec/fixtures/requests/id_range64.dat +0 -0
  43. data/spec/fixtures/requests/index_weights.dat +0 -0
  44. data/spec/fixtures/requests/keywords.dat +0 -0
  45. data/spec/fixtures/requests/limits.dat +0 -0
  46. data/spec/fixtures/requests/limits_cutoff.dat +0 -0
  47. data/spec/fixtures/requests/limits_max.dat +0 -0
  48. data/spec/fixtures/requests/limits_max_cutoff.dat +0 -0
  49. data/spec/fixtures/requests/match_all.dat +0 -0
  50. data/spec/fixtures/requests/match_any.dat +0 -0
  51. data/spec/fixtures/requests/match_boolean.dat +0 -0
  52. data/spec/fixtures/requests/match_extended.dat +0 -0
  53. data/spec/fixtures/requests/match_extended2.dat +0 -0
  54. data/spec/fixtures/requests/match_fullscan.dat +0 -0
  55. data/spec/fixtures/requests/match_phrase.dat +0 -0
  56. data/spec/fixtures/requests/max_query_time.dat +0 -0
  57. data/spec/fixtures/requests/miltiple_queries.dat +0 -0
  58. data/spec/fixtures/requests/outer_select.dat +0 -0
  59. data/spec/fixtures/requests/override.dat +0 -0
  60. data/spec/fixtures/{default_search.php → requests/php/default_search.php} +1 -1
  61. data/spec/fixtures/{default_search_index.php → requests/php/default_search_index.php} +1 -1
  62. data/spec/fixtures/{excerpt_custom.php → requests/php/excerpt_custom.php} +1 -1
  63. data/spec/fixtures/{excerpt_default.php → requests/php/excerpt_default.php} +1 -1
  64. data/spec/fixtures/{excerpt_flags.php → requests/php/excerpt_flags.php} +1 -1
  65. data/spec/fixtures/{field_weights.php → requests/php/field_weights.php} +1 -1
  66. data/spec/fixtures/{filter.php → requests/php/filter.php} +1 -1
  67. data/spec/fixtures/{filter_exclude.php → requests/php/filter_exclude.php} +1 -1
  68. data/spec/fixtures/{filter_float_range.php → requests/php/filter_float_range.php} +1 -1
  69. data/spec/fixtures/{filter_float_range_exclude.php → requests/php/filter_float_range_exclude.php} +1 -1
  70. data/spec/fixtures/{filter_range.php → requests/php/filter_range.php} +1 -1
  71. data/spec/fixtures/{filter_range_exclude.php → requests/php/filter_range_exclude.php} +1 -1
  72. data/spec/fixtures/{filter_range_int64.php → requests/php/filter_range_int64.php} +1 -1
  73. data/spec/fixtures/{filter_ranges.php → requests/php/filter_ranges.php} +1 -1
  74. data/spec/fixtures/{filters.php → requests/php/filters.php} +1 -1
  75. data/spec/fixtures/{filters_different.php → requests/php/filters_different.php} +1 -1
  76. data/spec/fixtures/{geo_anchor.php → requests/php/geo_anchor.php} +1 -1
  77. data/spec/fixtures/{group_by_attr.php → requests/php/group_by_attr.php} +1 -1
  78. data/spec/fixtures/{group_by_attrpair.php → requests/php/group_by_attrpair.php} +1 -1
  79. data/spec/fixtures/{group_by_day.php → requests/php/group_by_day.php} +1 -1
  80. data/spec/fixtures/{group_by_day_sort.php → requests/php/group_by_day_sort.php} +1 -1
  81. data/spec/fixtures/{group_by_month.php → requests/php/group_by_month.php} +1 -1
  82. data/spec/fixtures/{group_by_week.php → requests/php/group_by_week.php} +1 -1
  83. data/spec/fixtures/{group_by_year.php → requests/php/group_by_year.php} +1 -1
  84. data/spec/fixtures/{group_distinct.php → requests/php/group_distinct.php} +1 -1
  85. data/spec/fixtures/{id_range.php → requests/php/id_range.php} +1 -1
  86. data/spec/fixtures/{id_range64.php → requests/php/id_range64.php} +1 -1
  87. data/spec/fixtures/{index_weights.php → requests/php/index_weights.php} +1 -1
  88. data/spec/fixtures/{keywords.php → requests/php/keywords.php} +1 -1
  89. data/spec/fixtures/{limits.php → requests/php/limits.php} +1 -1
  90. data/spec/fixtures/{limits_cutoff.php → requests/php/limits_cutoff.php} +1 -1
  91. data/spec/fixtures/{limits_max.php → requests/php/limits_max.php} +1 -1
  92. data/spec/fixtures/{limits_max_cutoff.php → requests/php/limits_max_cutoff.php} +1 -1
  93. data/spec/fixtures/{match_all.php → requests/php/match_all.php} +1 -1
  94. data/spec/fixtures/{match_any.php → requests/php/match_any.php} +1 -1
  95. data/spec/fixtures/{match_boolean.php → requests/php/match_boolean.php} +1 -1
  96. data/spec/fixtures/{match_extended.php → requests/php/match_extended.php} +1 -1
  97. data/spec/fixtures/{match_extended2.php → requests/php/match_extended2.php} +1 -1
  98. data/spec/fixtures/{match_fullscan.php → requests/php/match_fullscan.php} +1 -1
  99. data/spec/fixtures/{match_phrase.php → requests/php/match_phrase.php} +1 -1
  100. data/spec/fixtures/{max_query_time.php → requests/php/max_query_time.php} +1 -1
  101. data/spec/fixtures/{miltiple_queries.php → requests/php/miltiple_queries.php} +1 -1
  102. data/spec/fixtures/requests/php/outer_select.php +9 -0
  103. data/spec/fixtures/{set_override.php → requests/php/override.php} +1 -1
  104. data/spec/fixtures/requests/php/query_flag.php +13 -0
  105. data/spec/fixtures/requests/php/query_flag_after_reset.php +19 -0
  106. data/spec/fixtures/{ranking_bm25.php → requests/php/ranking_bm25.php} +1 -1
  107. data/spec/fixtures/requests/php/ranking_expr.php +9 -0
  108. data/spec/fixtures/{ranking_fieldmask.php → requests/php/ranking_fieldmask.php} +1 -1
  109. data/spec/fixtures/{ranking_matchany.php → requests/php/ranking_matchany.php} +1 -1
  110. data/spec/fixtures/{ranking_none.php → requests/php/ranking_none.php} +1 -1
  111. data/spec/fixtures/{ranking_proximity.php → requests/php/ranking_proximity.php} +1 -1
  112. data/spec/fixtures/{ranking_proximity_bm25.php → requests/php/ranking_proximity_bm25.php} +1 -1
  113. data/spec/fixtures/{ranking_sph04.php → requests/php/ranking_sph04.php} +1 -1
  114. data/spec/fixtures/{ranking_wordcount.php → requests/php/ranking_wordcount.php} +1 -1
  115. data/spec/fixtures/{retries.php → requests/php/retries.php} +1 -1
  116. data/spec/fixtures/{retries_delay.php → requests/php/retries_delay.php} +1 -1
  117. data/spec/fixtures/{select.php → requests/php/select.php} +1 -1
  118. data/spec/fixtures/{sort_attr_asc.php → requests/php/sort_attr_asc.php} +1 -1
  119. data/spec/fixtures/{sort_attr_desc.php → requests/php/sort_attr_desc.php} +1 -1
  120. data/spec/fixtures/{sort_expr.php → requests/php/sort_expr.php} +1 -1
  121. data/spec/fixtures/{sort_extended.php → requests/php/sort_extended.php} +1 -1
  122. data/spec/fixtures/{sort_relevance.php → requests/php/sort_relevance.php} +1 -1
  123. data/spec/fixtures/{sort_time_segments.php → requests/php/sort_time_segments.php} +1 -1
  124. data/spec/fixtures/{update_attributes.php → requests/php/update_attributes.php} +1 -1
  125. data/spec/fixtures/{update_attributes_mva.php → requests/php/update_attributes_mva.php} +1 -1
  126. data/spec/fixtures/{weights.php → requests/php/weights.php} +1 -1
  127. data/spec/fixtures/requests/query_flag.dat +0 -0
  128. data/spec/fixtures/requests/query_flag_after_reset.dat +0 -0
  129. data/spec/fixtures/requests/ranking_bm25.dat +0 -0
  130. data/spec/fixtures/requests/ranking_expr.dat +0 -0
  131. data/spec/fixtures/requests/ranking_fieldmask.dat +0 -0
  132. data/spec/fixtures/requests/ranking_matchany.dat +0 -0
  133. data/spec/fixtures/requests/ranking_none.dat +0 -0
  134. data/spec/fixtures/requests/ranking_proximity.dat +0 -0
  135. data/spec/fixtures/requests/ranking_proximity_bm25.dat +0 -0
  136. data/spec/fixtures/requests/ranking_sph04.dat +0 -0
  137. data/spec/fixtures/requests/ranking_wordcount.dat +0 -0
  138. data/spec/fixtures/requests/retries.dat +0 -0
  139. data/spec/fixtures/requests/retries_delay.dat +0 -0
  140. data/spec/fixtures/requests/select.dat +0 -0
  141. data/spec/fixtures/requests/sort_attr_asc.dat +0 -0
  142. data/spec/fixtures/requests/sort_attr_desc.dat +0 -0
  143. data/spec/fixtures/requests/sort_expr.dat +0 -0
  144. data/spec/fixtures/requests/sort_extended.dat +0 -0
  145. data/spec/fixtures/requests/sort_relevance.dat +0 -0
  146. data/spec/fixtures/requests/sort_time_segments.dat +0 -0
  147. data/spec/fixtures/requests/update_attributes.dat +0 -0
  148. data/spec/fixtures/requests/update_attributes_mva.dat +0 -0
  149. data/spec/fixtures/requests/weights.dat +0 -0
  150. data/spec/fixtures/responses/build_excerpts.dat +0 -0
  151. data/spec/fixtures/responses/build_keywords.dat +0 -0
  152. data/spec/fixtures/responses/flush_attributes.dat +0 -0
  153. data/spec/fixtures/responses/flush_attrs.dat +2 -0
  154. data/spec/fixtures/responses/open.dat +0 -0
  155. data/spec/fixtures/responses/open_twice.dat +0 -0
  156. data/spec/fixtures/responses/php/build_excerpts.php +8 -0
  157. data/spec/fixtures/responses/php/build_keywords.php +8 -0
  158. data/spec/fixtures/responses/php/flush_attributes.php +8 -0
  159. data/spec/fixtures/responses/php/open.php +8 -0
  160. data/spec/fixtures/responses/php/open_twice.php +9 -0
  161. data/spec/fixtures/responses/php/query.php +8 -0
  162. data/spec/fixtures/responses/php/query_error.php +8 -0
  163. data/spec/fixtures/responses/php/query_id64.php +8 -0
  164. data/spec/fixtures/responses/php/run_queries.php +10 -0
  165. data/spec/fixtures/responses/php/run_queries_error.php +9 -0
  166. data/spec/fixtures/responses/php/status.php +8 -0
  167. data/spec/fixtures/responses/php/update_attributes.php +8 -0
  168. data/spec/fixtures/responses/php/update_attributes_mva.php +8 -0
  169. data/spec/fixtures/responses/query.dat +0 -0
  170. data/spec/fixtures/responses/query_error.dat +0 -0
  171. data/spec/fixtures/responses/query_id64.dat +0 -0
  172. data/spec/fixtures/responses/run_queries.dat +0 -0
  173. data/spec/fixtures/responses/run_queries_error.dat +0 -0
  174. data/spec/fixtures/responses/status.dat +0 -0
  175. data/spec/fixtures/responses/update_attributes.dat +0 -0
  176. data/spec/fixtures/responses/update_attributes_mva.dat +0 -0
  177. data/spec/fixtures/sphinxapi.php +217 -45
  178. data/spec/spec_helper.rb +18 -3
  179. data/spec/sphinx/sphinx-id64.conf +6 -6
  180. data/spec/sphinx/sphinx.conf +6 -6
  181. data/sphinx.gemspec +19 -121
  182. metadata +268 -105
  183. data/README.rdoc +0 -243
  184. data/VERSION.yml +0 -5
  185. data/init.rb +0 -1
@@ -24,9 +24,6 @@ module Sphinx
24
24
  # status command
25
25
  # @private
26
26
  SEARCHD_COMMAND_STATUS = 5
27
- # query command
28
- # @private
29
- SEARCHD_COMMAND_QUERY = 6
30
27
  # flushattrs command
31
28
  # @private
32
29
  SEARCHD_COMMAND_FLUSHATTRS = 7
@@ -37,13 +34,13 @@ module Sphinx
37
34
 
38
35
  # search command version
39
36
  # @private
40
- VER_COMMAND_SEARCH = 0x117
37
+ VER_COMMAND_SEARCH = 0x11D
41
38
  # excerpt command version
42
39
  # @private
43
- VER_COMMAND_EXCERPT = 0x100
40
+ VER_COMMAND_EXCERPT = 0x104
44
41
  # update command version
45
42
  # @private
46
- VER_COMMAND_UPDATE = 0x102
43
+ VER_COMMAND_UPDATE = 0x103
47
44
  # keywords command version
48
45
  # @private
49
46
  VER_COMMAND_KEYWORDS = 0x100
@@ -116,6 +113,8 @@ module Sphinx
116
113
  SPH_RANK_FIELDMASK = 6
117
114
  # codename SPH04, phrase proximity + bm25 + head/exact boost
118
115
  SPH_RANK_SPH04 = 7
116
+ # lets you specify the ranking formula in run time
117
+ SPH_RANK_EXPR = 8
119
118
 
120
119
  #=================================================================
121
120
  # Known sort modes
@@ -164,8 +163,12 @@ module Sphinx
164
163
  SPH_ATTR_BIGINT = 6
165
164
  # string (binary; in-memory)
166
165
  SPH_ATTR_STRING = 7
166
+ # ???
167
+ SPH_ATTR_FACTORS = 1001
167
168
  # this attr has multiple values (0 or more)
168
- SPH_ATTR_MULTI = 0x40000000
169
+ SPH_ATTR_MULTI = 0x40000001
170
+ # this attr has multiple 64-bit values (0 or more)
171
+ SPH_ATTR_MULTI64 = 0x40000002
169
172
 
170
173
  #=================================================================
171
174
  # Known grouping functions
@@ -183,7 +186,19 @@ module Sphinx
183
186
  SPH_GROUPBY_ATTR = 4
184
187
  # group by sequential attrs pair
185
188
  SPH_GROUPBY_ATTRPAIR = 5
189
+
190
+ #=================================================================
191
+ # Known query flags
192
+ #=================================================================
193
+
194
+ QUERY_FLAGS = HashWithIndifferentAccess.new(
195
+ :reverse_scan => { :values => [ 0, 1 ], :index => 0 },
196
+ :sort_method => { :values => ['pq', 'kbuffer' ], :index => 1 },
197
+ :max_predicted_time => { :values => lambda { |x| x > 0 }, :index => 2 },
198
+ :boolean_simplify => { :values => [ false, true ], :index => 3 },
199
+ :idf => { :values => [ 'normalized', 'plain' ], :index => 4 }
200
+ )
186
201
  end
187
202
 
188
203
  include Constants
189
- end
204
+ end
@@ -10,17 +10,17 @@ module Sphinx
10
10
  @position = 0
11
11
  @size = response.length
12
12
  end
13
-
13
+
14
14
  # Gets current stream position.
15
15
  def position
16
16
  @position
17
17
  end
18
-
18
+
19
19
  # Gets response size.
20
20
  def size
21
21
  @size
22
22
  end
23
-
23
+
24
24
  # Returns <tt>true</tt> when response stream is out.
25
25
  def eof?
26
26
  @position >= @size
@@ -50,7 +50,7 @@ module Sphinx
50
50
  @position += length
51
51
  return values
52
52
  end
53
-
53
+
54
54
  # Get string from stream.
55
55
  def get_string
56
56
  length = get_int
@@ -59,7 +59,7 @@ module Sphinx
59
59
  @position += length
60
60
  return value
61
61
  end
62
-
62
+
63
63
  # Get float from stream.
64
64
  def get_float
65
65
  raise EOFError if @position + 4 > @size
@@ -68,4 +68,4 @@ module Sphinx
68
68
  return ([uval].pack('L')).unpack('f*').first
69
69
  end
70
70
  end
71
- end
71
+ end
@@ -12,8 +12,7 @@ module Sphinx
12
12
  require 'system_timer'
13
13
  Timeout = ::SystemTimer
14
14
  end
15
- rescue LoadError => e
16
- puts "[sphinx] Could not load SystemTimer gem, falling back to Ruby's slower/unsafe timeout library: #{e.message}"
15
+ rescue LoadError
17
16
  require 'timeout'
18
17
  Timeout = ::Timeout
19
18
  end
@@ -0,0 +1,3 @@
1
+ module Sphinx
2
+ VERSION = '2.1.1.3711'
3
+ end
@@ -6,30 +6,41 @@ describe Sphinx::Client, 'connected' do
6
6
  before :each do
7
7
  @sphinx = Sphinx::Client.new
8
8
  end
9
-
9
+
10
+ def mock_sphinx_response(fixture)
11
+ response = sphinx_fixture(fixture, :response)
12
+ @sock = SphinxFakeSocket.new(response, 'rb')
13
+ servers = @sphinx.instance_variable_get(:@servers)
14
+ servers.first.stub(:get_socket => @sock)
15
+ end
16
+
10
17
  context 'in Query method' do
11
18
  it 'should parse response' do
19
+ mock_sphinx_response('query')
12
20
  result = @sphinx.Query('wifi', 'test1')
13
21
  validate_results_wifi(result)
14
22
  end
15
23
 
16
24
  it 'should process 64-bit keys' do
25
+ mock_sphinx_response('query_id64')
17
26
  result = @sphinx.Query('wifi', 'test2')
18
- result['total_found'].should == 3
19
- result['matches'].length.should == 3
20
- result['matches'][0]['id'].should == 4294967298
21
- result['matches'][1]['id'].should == 4294967299
22
- result['matches'][2]['id'].should == 4294967297
27
+ result['total_found'].should eq(3)
28
+ result['matches'].length.should eq(3)
29
+ result['matches'][0]['id'].should eq(4294967298)
30
+ result['matches'][1]['id'].should eq(4294967299)
31
+ result['matches'][2]['id'].should eq(4294967297)
23
32
  end
24
33
 
25
34
  it 'should process errors in Query method' do
35
+ mock_sphinx_response('query_error')
26
36
  @sphinx.Query('wifi', 'fakeindex').should be_false
27
- @sphinx.GetLastError.should_not be_empty
37
+ @sphinx.GetLastError.should =~ /unknown local index/
28
38
  end
29
39
  end
30
-
40
+
31
41
  context 'in RunQueries method' do
32
42
  it 'should parse batch-query responce' do
43
+ mock_sphinx_response('run_queries')
33
44
  @sphinx.AddQuery('wifi', 'test1')
34
45
  @sphinx.AddQuery('gprs', 'test1')
35
46
  results = @sphinx.RunQueries
@@ -39,6 +50,7 @@ describe Sphinx::Client, 'connected' do
39
50
  end
40
51
 
41
52
  it 'should process errors in RunQueries method' do
53
+ mock_sphinx_response('run_queries_error')
42
54
  @sphinx.AddQuery('wifi', 'fakeindex')
43
55
  r = @sphinx.RunQueries
44
56
  r[0]['error'].should_not be_empty
@@ -47,132 +59,133 @@ describe Sphinx::Client, 'connected' do
47
59
 
48
60
  context 'in BuildExcerpts method' do
49
61
  it 'should parse response' do
62
+ mock_sphinx_response('build_excerpts')
50
63
  result = @sphinx.BuildExcerpts(['what the world', 'London is the capital of Great Britain'], 'test1', 'the')
51
- result.should == ['what <b>the</b> world', 'London is <b>the</b> capital of Great Britain']
64
+ result.should eq(['what <b>the</b> world', 'London is <b>the</b> capital of Great Britain'])
52
65
  end
53
66
  end
54
67
 
55
68
  context 'in BuildKeywords method' do
56
69
  it 'should parse response' do
70
+ mock_sphinx_response('build_keywords')
57
71
  result = @sphinx.BuildKeywords('wifi gprs', 'test1', true)
58
- result.should == [
72
+ result.should eq([
59
73
  { 'normalized' => 'wifi', 'tokenized' => 'wifi', 'hits' => 6, 'docs' => 3 },
60
74
  { 'normalized' => 'gprs', 'tokenized' => 'gprs', 'hits' => 1, 'docs' => 1 }
61
- ]
75
+ ])
62
76
  end
63
77
  end
64
78
 
65
79
  context 'in UpdateAttributes method' do
66
80
  it 'should parse response' do
67
- @sphinx.UpdateAttributes('test1', ['group_id'], { 2 => [1] }).should == 1
68
- result = @sphinx.Query('wifi', 'test1')
69
- result['matches'][0]['attrs']['group_id'].should == 1
70
- @sphinx.UpdateAttributes('test1', ['group_id'], { 2 => [2] }).should == 1
71
- result = @sphinx.Query('wifi', 'test1')
72
- result['matches'][0]['attrs']['group_id'].should == 2
81
+ mock_sphinx_response('update_attributes')
82
+ @sphinx.UpdateAttributes('test1', ['group_id'], { 2 => [1] }).should eq(1)
73
83
  end
74
84
 
75
85
  it 'should parse response with MVA' do
76
- @sphinx.UpdateAttributes('test1', ['tags'], { 2 => [[1, 2, 3, 4, 5, 6, 7, 8, 9]] }, true).should == 1
77
- result = @sphinx.Query('wifi', 'test1')
78
- result['matches'][0]['attrs']['tags'].should == [1, 2, 3, 4, 5, 6, 7, 8, 9]
79
- @sphinx.UpdateAttributes('test1', ['tags'], { 2 => [[5, 6, 7, 8]] }, true).should == 1
80
- result = @sphinx.Query('wifi', 'test1')
81
- result['matches'][0]['attrs']['tags'].should == [5, 6, 7, 8]
86
+ mock_sphinx_response('update_attributes_mva')
87
+ @sphinx.UpdateAttributes('test1', ['tags'], { 2 => [[1, 2, 3, 4, 5, 6, 7, 8, 9]] }, true).should eq(1)
82
88
  end
83
89
  end
84
90
 
85
91
  context 'in Open method' do
86
92
  it 'should open socket' do
93
+ mock_sphinx_response('open')
87
94
  @sphinx.Open.should be_true
88
95
  socket = @sphinx.servers.first.instance_variable_get(:@socket)
89
- socket.should_not be_nil
90
- socket.should be_kind_of(Sphinx::BufferedIO)
96
+ socket.should eq(@sock)
91
97
  socket.close
92
98
  end
93
-
99
+
94
100
  it 'should produce an error when opened twice' do
101
+ mock_sphinx_response('open')
102
+ sock = @sock
95
103
  @sphinx.Open.should be_true
104
+ mock_sphinx_response('open_twice')
96
105
  @sphinx.Open.should be_false
97
- @sphinx.GetLastError.should == 'already connected'
98
-
106
+ @sphinx.GetLastError.should eq('already connected')
107
+
99
108
  socket = @sphinx.servers.first.instance_variable_get(:@socket)
100
- socket.should be_kind_of(Sphinx::BufferedIO)
109
+ socket.should eq(sock)
101
110
  socket.close
102
111
  end
103
112
  end
104
-
113
+
105
114
  context 'in Close method' do
106
115
  it 'should open socket' do
116
+ mock_sphinx_response('open')
107
117
  @sphinx.Open.should be_true
108
118
  @sphinx.Close.should be_true
109
119
  @sphinx.servers.first.instance_variable_get(:@socket).should be_nil
110
120
  end
111
-
121
+
112
122
  it 'should produce socket is closed' do
113
123
  @sphinx.Close.should be_false
114
- @sphinx.GetLastError.should == 'not connected'
124
+ @sphinx.GetLastError.should eq('not connected')
115
125
  @sphinx.servers.first.instance_variable_get(:@socket).should be_nil
116
-
126
+
127
+ mock_sphinx_response('open')
117
128
  @sphinx.Open.should be_true
118
129
  @sphinx.Close.should be_true
119
130
  @sphinx.Close.should be_false
120
- @sphinx.GetLastError.should == 'not connected'
131
+ @sphinx.GetLastError.should eq('not connected')
121
132
  @sphinx.servers.first.instance_variable_get(:@socket).should be_nil
122
133
  end
123
134
  end
124
135
 
125
136
  context 'in Status method' do
126
137
  it 'should parse response' do
138
+ mock_sphinx_response('status')
127
139
  response = @sphinx.Status
128
140
  response.should be_an(Array)
129
141
  response.size.should be > 10
130
142
  end
131
143
  end
132
144
 
133
- context 'in FlushAttrs method' do
145
+ context 'in FlushAttributes method' do
134
146
  it 'should not raise an error' do
147
+ mock_sphinx_response('flush_attributes')
135
148
  expect {
136
- @sphinx.FlushAttrs
149
+ @sphinx.FlushAttributes
137
150
  }.to_not raise_error
138
151
  end
139
152
  end
140
153
 
141
154
  def validate_results_wifi(result)
142
- result['total_found'].should == 3
143
- result['matches'].length.should == 3
155
+ result['total_found'].should eq(3)
156
+ result['matches'].length.should eq(3)
144
157
  result['time'].should_not be_nil
145
- result['attrs'].should == {
158
+ result['attrs'].should eq({
146
159
  'group_id' => Sphinx::SPH_ATTR_INTEGER,
147
160
  'created_at' => Sphinx::SPH_ATTR_TIMESTAMP,
148
161
  'rating' => Sphinx::SPH_ATTR_FLOAT,
149
162
  'tags' => Sphinx::SPH_ATTR_MULTI | Sphinx::SPH_ATTR_INTEGER
150
- }
151
- result['fields'].should == [ 'name', 'description' ]
152
- result['total'].should == 3
163
+ })
164
+ result['fields'].should eq([ 'name', 'description' ])
165
+ result['total'].should eq(3)
153
166
  result['matches'].should be_an_instance_of(Array)
154
167
 
155
- result['matches'][0]['id'].should == 2
156
- result['matches'][0]['weight'].should == 2
157
- result['matches'][0]['attrs']['group_id'].should == 2
158
- result['matches'][0]['attrs']['created_at'].should == 1175658555
159
- result['matches'][0]['attrs']['tags'].should == [5, 6, 7, 8]
160
- ('%0.2f' % result['matches'][0]['attrs']['rating']).should == '54.85'
161
-
162
- result['matches'][1]['id'].should == 3
163
- result['matches'][1]['weight'].should == 2
164
- result['matches'][1]['attrs']['group_id'].should == 1
165
- result['matches'][1]['attrs']['created_at'].should == 1175658647
166
- result['matches'][1]['attrs']['tags'].should == [1, 7, 9, 10]
167
- ('%0.2f' % result['matches'][1]['attrs']['rating']).should == '16.25'
168
-
169
- result['matches'][2]['id'].should == 1
170
- result['matches'][2]['weight'].should == 1
171
- result['matches'][2]['attrs']['group_id'].should == 1
172
- result['matches'][2]['attrs']['created_at'].should == 1175658490
173
- result['matches'][2]['attrs']['tags'].should == [1, 2, 3, 4]
174
- ('%0.2f' % result['matches'][2]['attrs']['rating']).should == '13.32'
175
-
176
- result['words'].should == { 'wifi' => { 'hits' => 6, 'docs' => 3 } }
168
+ result['matches'][0]['id'].should eq(2)
169
+ result['matches'][0]['weight'].should eq(2)
170
+ result['matches'][0]['attrs']['group_id'].should eq(2)
171
+ result['matches'][0]['attrs']['created_at'].should eq(1175683755)
172
+ result['matches'][0]['attrs']['tags'].should eq([5, 6, 7, 8])
173
+ ('%0.2f' % result['matches'][0]['attrs']['rating']).should eq('54.85')
174
+
175
+ result['matches'][1]['id'].should eq(3)
176
+ result['matches'][1]['weight'].should eq(2)
177
+ result['matches'][1]['attrs']['group_id'].should eq(1)
178
+ result['matches'][1]['attrs']['created_at'].should eq(1175683847)
179
+ result['matches'][1]['attrs']['tags'].should eq([1, 7, 9, 10])
180
+ ('%0.2f' % result['matches'][1]['attrs']['rating']).should eq('16.25')
181
+
182
+ result['matches'][2]['id'].should eq(1)
183
+ result['matches'][2]['weight'].should eq(1)
184
+ result['matches'][2]['attrs']['group_id'].should eq(1)
185
+ result['matches'][2]['attrs']['created_at'].should eq(1175683690)
186
+ result['matches'][2]['attrs']['tags'].should eq([1, 2, 3, 4])
187
+ ('%0.2f' % result['matches'][2]['attrs']['rating']).should eq('13.32')
188
+
189
+ result['words'].should eq({ 'wifi' => { 'hits' => 6, 'docs' => 3 } })
177
190
  end
178
191
  end
@@ -20,7 +20,7 @@ describe Sphinx::Client, 'disconnected' do
20
20
  2.times do
21
21
  cnt = 0
22
22
  expect {
23
- @sphinx.send(:with_server) { |server| cnt += 1; server.should == @sphinx.servers[0]; raise Sphinx::SphinxConnectError }
23
+ @sphinx.send(:with_server) { |server| cnt += 1; server.should eq(@sphinx.servers[0]); raise Sphinx::SphinxConnectError }
24
24
  }.to raise_error(Sphinx::SphinxConnectError)
25
25
  cnt.should == 1
26
26
  end
@@ -29,24 +29,24 @@ describe Sphinx::Client, 'disconnected' do
29
29
  it 'should select server based on index' do
30
30
  @sphinx.SetServers(@servers)
31
31
  cnt = 0
32
- @sphinx.send(:with_server, 0) { |server| cnt += 1; server.should == @sphinx.servers[0] }
33
- cnt.should == 1
32
+ @sphinx.send(:with_server, 0) { |server| cnt += 1; server.should eq(@sphinx.servers[0]) }
33
+ cnt.should eq(1)
34
34
  cnt = 0
35
- @sphinx.send(:with_server, 1) { |server| cnt += 1; server.should == @sphinx.servers[1] }
36
- cnt.should == 1
35
+ @sphinx.send(:with_server, 1) { |server| cnt += 1; server.should eq(@sphinx.servers[1]) }
36
+ cnt.should eq(1)
37
37
  cnt = 0
38
- @sphinx.send(:with_server, 2) { |server| cnt += 1; server.should == @sphinx.servers[0] }
39
- cnt.should == 1
38
+ @sphinx.send(:with_server, 2) { |server| cnt += 1; server.should eq(@sphinx.servers[0]) }
39
+ cnt.should eq(1)
40
40
  end
41
41
 
42
42
  it 'should select given server' do
43
43
  @sphinx.SetServers(@servers)
44
44
  cnt = 0
45
45
  @sphinx.send(:with_server, @sphinx.servers[0]) { |server| cnt += 1; server.should == @sphinx.servers[0] }
46
- cnt.should == 1
46
+ cnt.should eq(1)
47
47
  cnt = 0
48
48
  @sphinx.send(:with_server, @sphinx.servers[1]) { |server| cnt += 1; server.should == @sphinx.servers[1] }
49
- cnt.should == 1
49
+ cnt.should eq(1)
50
50
  end
51
51
  end
52
52
 
@@ -58,36 +58,36 @@ describe Sphinx::Client, 'disconnected' do
58
58
  it 'should raise an exception on error' do
59
59
  cnt = 0
60
60
  expect {
61
- @sphinx.send(:with_server) { |server| cnt += 1; server.should == @sphinx.servers[0]; raise Sphinx::SphinxConnectError }
61
+ @sphinx.send(:with_server) { |server| cnt += 1; server.should eq(@sphinx.servers[0]); raise Sphinx::SphinxConnectError }
62
62
  }.to raise_error(Sphinx::SphinxConnectError)
63
- cnt.should == 3
63
+ cnt.should eq(3)
64
64
  end
65
65
 
66
66
  it 'should round-robin servers and raise an exception on error' do
67
67
  @sphinx.SetServers(@servers)
68
68
  cnt = 0
69
69
  expect {
70
- @sphinx.send(:with_server) { |server| cnt += 1; server.should == @sphinx.servers[(cnt - 1) % 2]; raise Sphinx::SphinxConnectError }
70
+ @sphinx.send(:with_server) { |server| cnt += 1; server.should eq(@sphinx.servers[(cnt - 1) % 2]); raise Sphinx::SphinxConnectError }
71
71
  }.to raise_error(Sphinx::SphinxConnectError)
72
- cnt.should == 3
72
+ cnt.should eq(3)
73
73
  end
74
74
 
75
75
  it 'should round-robin servers with respect to passed index and raise an exception on error' do
76
76
  @sphinx.SetServers(@servers)
77
77
  cnt = 0
78
78
  expect {
79
- @sphinx.send(:with_server, 1) { |server| cnt += 1; server.should == @sphinx.servers[cnt % 2]; raise Sphinx::SphinxConnectError }
79
+ @sphinx.send(:with_server, 1) { |server| cnt += 1; server.should eq(@sphinx.servers[cnt % 2]); raise Sphinx::SphinxConnectError }
80
80
  }.to raise_error(Sphinx::SphinxConnectError)
81
- cnt.should == 3
81
+ cnt.should eq(3)
82
82
  end
83
83
 
84
84
  it 'should round-robin with respect to attempts number passed' do
85
85
  @sphinx.SetServers(@servers)
86
86
  cnt = 0
87
87
  expect {
88
- @sphinx.send(:with_server, 0, 5) { |server| cnt += 1; server.should == @sphinx.servers[(cnt - 1) % 2]; raise Sphinx::SphinxConnectError }
88
+ @sphinx.send(:with_server, 0, 5) { |server| cnt += 1; server.should eq(@sphinx.servers[(cnt - 1) % 2]); raise Sphinx::SphinxConnectError }
89
89
  }.to raise_error(Sphinx::SphinxConnectError)
90
- cnt.should == 5
90
+ cnt.should eq(5)
91
91
  end
92
92
  end
93
93
  end
@@ -110,7 +110,7 @@ describe Sphinx::Client, 'disconnected' do
110
110
  @socket.should_receive(:read).with(4).and_return([1].pack('N'))
111
111
  cnt = 0
112
112
  @sphinx.send(:with_socket, @server) { |socket| cnt += 1; socket.should == @socket }
113
- cnt.should == 1
113
+ cnt.should eq(1)
114
114
  end
115
115
 
116
116
  it 'should raise exception when searchd protocol is not 1+' do
@@ -120,7 +120,7 @@ describe Sphinx::Client, 'disconnected' do
120
120
  expect {
121
121
  @sphinx.send(:with_socket, @server) { cnt += 1; }
122
122
  }.to raise_error(Sphinx::SphinxConnectError, 'expected searchd protocol version 1+, got version \'0\'')
123
- cnt.should == 0
123
+ cnt.should eq(0)
124
124
  end
125
125
 
126
126
  it 'should handle request timeouts' do
@@ -130,10 +130,10 @@ describe Sphinx::Client, 'disconnected' do
130
130
  cnt = 0
131
131
  expect {
132
132
  @sphinx.send(:with_socket, @server) { cnt += 1; sleep 2 }
133
- }.to raise_error(Sphinx::SphinxResponseError, 'failed to read searchd response (msg=time\'s up!)')
134
- cnt.should == 1
133
+ }.to raise_error(Sphinx::SphinxResponseError, 'failed to read searchd response (msg=execution expired)')
134
+ cnt.should eq(1)
135
135
 
136
- @sphinx.GetLastError.should == 'failed to read searchd response (msg=time\'s up!)'
136
+ @sphinx.GetLastError.should eq('failed to read searchd response (msg=execution expired)')
137
137
  @sphinx.IsConnectError.should be_false
138
138
  end
139
139
 
@@ -144,9 +144,9 @@ describe Sphinx::Client, 'disconnected' do
144
144
  expect {
145
145
  @sphinx.send(:with_socket, @server) { cnt += 1; raise Sphinx::SphinxInternalError, 'hello' }
146
146
  }.to raise_error(Sphinx::SphinxInternalError, 'hello')
147
- cnt.should == 1
147
+ cnt.should eq(1)
148
148
 
149
- @sphinx.GetLastError.should == 'hello'
149
+ @sphinx.GetLastError.should eq('hello')
150
150
  @sphinx.IsConnectError.should be_false
151
151
  end
152
152
  end
@@ -167,9 +167,9 @@ describe Sphinx::Client, 'disconnected' do
167
167
  expect {
168
168
  @sphinx.send(:with_socket, @server) { cnt += 1; raise Sphinx::SphinxInternalError, 'hello' }
169
169
  }.to raise_error(Sphinx::SphinxInternalError, 'hello')
170
- cnt.should == 3
170
+ cnt.should eq(3)
171
171
 
172
- @sphinx.GetLastError.should == 'hello'
172
+ @sphinx.GetLastError.should eq('hello')
173
173
  @sphinx.IsConnectError.should be_false
174
174
  end
175
175
  end
@@ -206,7 +206,7 @@ describe Sphinx::Client, 'disconnected' do
206
206
  @socket.should_receive(:read).with(8).and_return([Sphinx::SEARCHD_WARNING, 1, 14].pack('n2N'))
207
207
  @socket.should_receive(:read).with(14).and_return([5].pack('N') + 'helloworld')
208
208
  @sphinx.send(:parse_response, @socket, 1).should == 'world'
209
- @sphinx.GetLastWarning.should == 'hello'
209
+ @sphinx.GetLastWarning.should eq('hello')
210
210
  end
211
211
 
212
212
  it 'should raise exception when SEARCHD_ERROR received' do
@@ -313,24 +313,26 @@ describe Sphinx::Client, 'disconnected' do
313
313
 
314
314
  describe 'with rank' do
315
315
  [ :proximity_bm25, :bm25, :none, :wordcount, :proximity, :matchany, :fieldmask, :sph04 ].each do |rank|
316
+ expr = rank == :expr ? '' : 'sum(lcs*user_weight)*1000+bm25'
317
+
316
318
  it "should generate valid request for SPH_RANK_#{rank.to_s.upcase}" do
317
319
  expected = sphinx_fixture("ranking_#{rank}")
318
320
  @sock.should_receive(:write).with(expected)
319
- @sphinx.SetRankingMode(Sphinx::Client.const_get("SPH_RANK_#{rank.to_s.upcase}"))
321
+ @sphinx.SetRankingMode(Sphinx::Client.const_get("SPH_RANK_#{rank.to_s.upcase}"), expr)
320
322
  sphinx_safe_call { @sphinx.Query('query') }
321
323
  end
322
324
 
323
325
  it "should generate valid request for \"#{rank}\"" do
324
326
  expected = sphinx_fixture("ranking_#{rank}")
325
327
  @sock.should_receive(:write).with(expected)
326
- @sphinx.SetRankingMode(rank.to_s)
328
+ @sphinx.SetRankingMode(rank.to_s, expr)
327
329
  sphinx_safe_call { @sphinx.Query('query') }
328
330
  end
329
331
 
330
332
  it "should generate valid request for :#{rank}" do
331
333
  expected = sphinx_fixture("ranking_#{rank}")
332
334
  @sock.should_receive(:write).with(expected)
333
- @sphinx.SetRankingMode(rank)
335
+ @sphinx.SetRankingMode(rank, expr)
334
336
  sphinx_safe_call { @sphinx.Query('query') }
335
337
  end
336
338
  end
@@ -535,7 +537,7 @@ describe Sphinx::Client, 'disconnected' do
535
537
  end
536
538
 
537
539
  it 'should generate valid request for SetOverride' do
538
- expected = sphinx_fixture('set_override')
540
+ expected = sphinx_fixture('override')
539
541
  @sock.should_receive(:write).with(expected)
540
542
  @sphinx.SetOverride('attr1', Sphinx::SPH_ATTR_INTEGER, { 10 => 20 })
541
543
  @sphinx.SetOverride('attr2', Sphinx::SPH_ATTR_FLOAT, { 11 => 30.3 })
@@ -549,6 +551,41 @@ describe Sphinx::Client, 'disconnected' do
549
551
  @sphinx.SetSelect('attr1, attr2')
550
552
  sphinx_safe_call { @sphinx.Query('query') }
551
553
  end
554
+
555
+ it 'should generate valid request for SetOuterSelect' do
556
+ expected = sphinx_fixture('outer_select')
557
+ @sock.should_receive(:write).with(expected)
558
+ @sphinx.SetOuterSelect('attr', 10, 100)
559
+ sphinx_safe_call { @sphinx.Query('query') }
560
+ end
561
+
562
+ it 'should generate valid request for SetQueryFlag' do
563
+ expected = sphinx_fixture('query_flag')
564
+ @sock.should_receive(:write).with(expected)
565
+ @sphinx.SetQueryFlag('reverse_scan', 1)
566
+ @sphinx.SetQueryFlag('sort_method', 'kbuffer')
567
+ @sphinx.SetQueryFlag('max_predicted_time', 15)
568
+ @sphinx.SetQueryFlag('boolean_simplify', true)
569
+ @sphinx.SetQueryFlag('idf', 'plain')
570
+ sphinx_safe_call { @sphinx.Query('query') }
571
+ end
572
+
573
+ it 'should generate valid request for SetQueryFlag after flag reset' do
574
+ expected = sphinx_fixture('query_flag_after_reset')
575
+ @sock.should_receive(:write).with(expected)
576
+ @sphinx.SetQueryFlag('reverse_scan', 1)
577
+ @sphinx.SetQueryFlag('sort_method', 'kbuffer')
578
+ @sphinx.SetQueryFlag('max_predicted_time', 15)
579
+ @sphinx.SetQueryFlag('boolean_simplify', true)
580
+ @sphinx.SetQueryFlag('idf', 'plain')
581
+
582
+ @sphinx.SetQueryFlag('reverse_scan', 0)
583
+ @sphinx.SetQueryFlag('sort_method', 'pq')
584
+ @sphinx.SetQueryFlag('max_predicted_time', 0)
585
+ @sphinx.SetQueryFlag('boolean_simplify', false)
586
+ @sphinx.SetQueryFlag('idf', 'normalized')
587
+ sphinx_safe_call { @sphinx.Query('query') }
588
+ end
552
589
  end
553
590
 
554
591
  context 'in RunQueries method' do